2021-08-04 23:31:54 +00:00
|
|
|
//
|
|
|
|
// Copyright © 2020, 2021 Anticrm Platform Contributors.
|
|
|
|
//
|
|
|
|
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License. You may
|
|
|
|
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
//
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
//
|
|
|
|
|
2023-06-20 05:47:00 +00:00
|
|
|
import { derived, get, writable } from 'svelte/store'
|
2023-04-12 08:20:01 +00:00
|
|
|
import { closePopup } from './popups'
|
2023-04-21 16:24:45 +00:00
|
|
|
import justClone from 'just-clone'
|
|
|
|
import { Location as PlatformLocation } from './types'
|
2021-08-04 23:31:54 +00:00
|
|
|
|
|
|
|
export function locationToUrl (location: PlatformLocation): string {
|
|
|
|
let result = '/'
|
|
|
|
if (location.path != null) {
|
|
|
|
result += location.path.map((p) => encodeURIComponent(p)).join('/')
|
|
|
|
}
|
|
|
|
if (location.query != null) {
|
|
|
|
const queryValue = Object.entries(location.query)
|
|
|
|
.map((e) => {
|
|
|
|
if (e[1] != null) {
|
|
|
|
// Had value
|
|
|
|
return e[0] + '=' + e[1]
|
|
|
|
} else {
|
|
|
|
return e[0]
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.join('&')
|
|
|
|
if (queryValue.length > 0) {
|
|
|
|
result += '?' + queryValue
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (location.fragment != null && location.fragment.length > 0) {
|
|
|
|
result += '#' + location.fragment
|
|
|
|
}
|
|
|
|
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
2022-06-27 13:55:52 +00:00
|
|
|
export function parseLocation (location: Location | URL): PlatformLocation {
|
2021-08-04 23:31:54 +00:00
|
|
|
return {
|
|
|
|
path: parsePath(location.pathname),
|
|
|
|
query: parseQuery(location.search),
|
|
|
|
fragment: parseHash(location.hash)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-26 07:31:15 +00:00
|
|
|
function parseQuery (query: string): Record<string, string | null> | undefined {
|
2021-08-04 23:31:54 +00:00
|
|
|
query = query.trim()
|
|
|
|
if (query.length === 0 || !query.startsWith('?')) {
|
2023-06-26 07:31:15 +00:00
|
|
|
return
|
2021-08-04 23:31:54 +00:00
|
|
|
}
|
2023-03-16 11:36:05 +00:00
|
|
|
query = decodeURIComponent(query).substring(1)
|
2021-08-04 23:31:54 +00:00
|
|
|
const vars = query.split('&')
|
|
|
|
const result: Record<string, string | null> = {}
|
|
|
|
for (let i = 0; i < vars.length; i++) {
|
|
|
|
const pair = vars[i].split('=')
|
|
|
|
const key = pair[0]
|
|
|
|
if (key.length > 0) {
|
|
|
|
if (pair.length > 1) {
|
|
|
|
const value = pair[1]
|
|
|
|
result[key] = value
|
|
|
|
} else {
|
|
|
|
result[key] = null
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
|
|
|
function parsePath (path: string): string[] {
|
|
|
|
const split = path.split('/').map((ps) => decodeURIComponent(ps))
|
|
|
|
if (split.length >= 1) {
|
|
|
|
if (split[0] === '') {
|
|
|
|
split.splice(0, 1)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (split.length >= 1) {
|
|
|
|
if (split[split.length - 1] === '') {
|
|
|
|
split.splice(split.length - 1, 1)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return split
|
|
|
|
}
|
|
|
|
|
|
|
|
function parseHash (hash: string): string {
|
|
|
|
if (hash.startsWith('#')) {
|
2023-03-16 11:36:05 +00:00
|
|
|
return decodeURIComponent(hash.substring(1))
|
2021-08-04 23:31:54 +00:00
|
|
|
}
|
2023-03-16 11:36:05 +00:00
|
|
|
return decodeURIComponent(hash)
|
2021-08-04 23:31:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------
|
|
|
|
|
2023-06-20 05:47:00 +00:00
|
|
|
export function getRawCurrentLocation (): PlatformLocation {
|
2021-08-04 23:31:54 +00:00
|
|
|
return parseLocation(window.location)
|
|
|
|
}
|
|
|
|
|
2023-04-21 16:24:45 +00:00
|
|
|
export function getCurrentResolvedLocation (): PlatformLocation {
|
|
|
|
return justClone(resolvedLocation)
|
|
|
|
}
|
|
|
|
|
2023-06-20 05:47:00 +00:00
|
|
|
declare global {
|
|
|
|
interface Window {
|
|
|
|
embeddedPlatform?: boolean
|
|
|
|
}
|
|
|
|
}
|
2023-08-19 09:00:43 +00:00
|
|
|
export const embeddedPlatform = window.embeddedPlatform ?? false
|
2023-06-22 16:04:19 +00:00
|
|
|
const locationWritable = writable(getRawCurrentLocation())
|
2023-06-20 05:47:00 +00:00
|
|
|
|
|
|
|
console.log('embeddedPlatform', window.embeddedPlatform)
|
|
|
|
|
|
|
|
if (!embeddedPlatform) {
|
|
|
|
window.addEventListener('popstate', () => {
|
|
|
|
locationWritable.set(getRawCurrentLocation())
|
|
|
|
})
|
2023-08-21 11:27:42 +00:00
|
|
|
} else {
|
|
|
|
window.addEventListener('popstate', (state) => {
|
|
|
|
if (state.state.location !== undefined) {
|
|
|
|
locationWritable.set(state.state.location)
|
|
|
|
}
|
|
|
|
})
|
2023-06-20 05:47:00 +00:00
|
|
|
}
|
2021-08-04 23:31:54 +00:00
|
|
|
|
2023-06-22 16:04:19 +00:00
|
|
|
export const location = derived(locationWritable, (loc) => justClone(loc))
|
|
|
|
|
2023-08-17 05:38:10 +00:00
|
|
|
export const workspaceId = derived(location, (loc) => loc.path[1])
|
|
|
|
|
2023-06-22 16:04:19 +00:00
|
|
|
/**
|
|
|
|
* @public
|
|
|
|
*/
|
|
|
|
export function getLocation (): PlatformLocation {
|
|
|
|
return justClone(get(location))
|
|
|
|
}
|
|
|
|
|
2023-06-20 05:47:00 +00:00
|
|
|
export const resolvedLocationStore = writable(getRawCurrentLocation())
|
|
|
|
let resolvedLocation = getRawCurrentLocation()
|
2023-04-21 16:24:45 +00:00
|
|
|
|
|
|
|
export function setResolvedLocation (location: PlatformLocation): void {
|
|
|
|
resolvedLocation = location
|
|
|
|
resolvedLocationStore.set(justClone(location))
|
|
|
|
}
|
2021-08-04 23:31:54 +00:00
|
|
|
|
2023-06-20 05:47:00 +00:00
|
|
|
export function getCurrentLocation (): PlatformLocation {
|
|
|
|
if (embeddedPlatform) {
|
|
|
|
return justClone(get(locationWritable))
|
|
|
|
}
|
|
|
|
return getRawCurrentLocation()
|
|
|
|
}
|
|
|
|
|
2023-06-26 14:03:12 +00:00
|
|
|
/**
|
|
|
|
* @public
|
|
|
|
*/
|
|
|
|
export let locationStorageKeyId = 'platform_last_loc'
|
|
|
|
|
|
|
|
export function setLocationStorageKey (storageKey: string): void {
|
|
|
|
locationStorageKeyId = storageKey
|
|
|
|
}
|
|
|
|
|
2023-06-08 17:42:00 +00:00
|
|
|
export function navigate (location: PlatformLocation, store = true): boolean {
|
2023-04-12 08:20:01 +00:00
|
|
|
closePopup()
|
2023-06-20 05:47:00 +00:00
|
|
|
const cur = locationToUrl(getCurrentLocation())
|
2021-08-04 23:31:54 +00:00
|
|
|
const url = locationToUrl(location)
|
2023-06-20 05:47:00 +00:00
|
|
|
if (cur !== url) {
|
2023-03-15 14:06:03 +00:00
|
|
|
if (store) {
|
2023-06-20 05:47:00 +00:00
|
|
|
if (!embeddedPlatform) {
|
|
|
|
history.pushState(null, '', url)
|
2023-08-21 11:27:42 +00:00
|
|
|
} else {
|
|
|
|
history.pushState({ location }, '')
|
2023-06-20 05:47:00 +00:00
|
|
|
}
|
2023-06-26 14:03:12 +00:00
|
|
|
localStorage.setItem(locationStorageKeyId, JSON.stringify(location))
|
2023-03-21 11:58:23 +00:00
|
|
|
if (location.path[1] !== undefined) {
|
2023-06-26 14:03:12 +00:00
|
|
|
localStorage.setItem(`${locationStorageKeyId}_${location.path[1]}`, JSON.stringify(location))
|
2023-03-21 11:58:23 +00:00
|
|
|
}
|
2023-03-15 14:06:03 +00:00
|
|
|
}
|
2022-02-08 16:01:57 +00:00
|
|
|
locationWritable.set(location)
|
2023-06-08 17:42:00 +00:00
|
|
|
return true
|
2022-02-08 16:01:57 +00:00
|
|
|
}
|
2023-06-08 17:42:00 +00:00
|
|
|
return false
|
2021-08-04 23:31:54 +00:00
|
|
|
}
|
2023-10-31 09:21:29 +00:00
|
|
|
|
|
|
|
const COLLAPSED = 'COLLAPSED'
|
|
|
|
export const getCollapsedKey = (_id: string): string => `${getCurrentLocation().path[1]}_${_id}_collapsed`
|
|
|
|
|
|
|
|
export const getTreeCollapsed = (_id: any): boolean => {
|
|
|
|
if (_id === undefined || _id === 'undefined') return false
|
|
|
|
return localStorage.getItem(getCollapsedKey(_id as string)) === COLLAPSED
|
|
|
|
}
|
|
|
|
|
|
|
|
export const setTreeCollapsed = (_id: any, collapsed: boolean): void => {
|
|
|
|
if (_id === undefined || _id === 'undefined') return
|
|
|
|
localStorage.setItem(getCollapsedKey(_id), collapsed ? COLLAPSED : '')
|
|
|
|
}
|