Refactoring: put all special visualisations into their own class, add their location into the documentation

This commit is contained in:
Pieter Vander Vennet 2025-06-26 05:20:12 +02:00
parent c0e7c9e8fa
commit ae5205f92d
29 changed files with 2270 additions and 2075 deletions

View file

@ -1,6 +1,5 @@
import { SpecialVisualizationState, SpecialVisualizationSvelte } from "../SpecialVisualization"
import SvelteUIElement from "../Base/SvelteUIElement"
import DisabledQuestions from "../Popup/DisabledQuestions.svelte"
import Constants from "../../Models/Constants"
import LogoutButton from "../Base/LogoutButton.svelte"
import LoginButton from "../Base/LoginButton.svelte"
@ -17,191 +16,234 @@ import { Utils } from "../../Utils"
import { Feature } from "geojson"
import LayerConfig from "../../Models/ThemeConfig/LayerConfig"
import QrCode from "../Popup/QrCode.svelte"
import ClearGPSHistory from "../BigComponents/ClearGPSHistory.svelte"
class LanguagePickerVis extends SpecialVisualizationSvelte {
funcName = "language_picker"
args = []
group = "settings"
docs = "A component to set the language of the user interface"
constr(state: SpecialVisualizationState): SvelteUIElement {
const availableLanguages = Locale.showLinkToWeblate.map((showTranslations) =>
showTranslations
? LanguageUtils.usedLanguagesSorted
: state?.theme?.language ?? LanguageUtils.usedLanguagesSorted,
)
return new SvelteUIElement(LanguagePicker, {
assignTo: state.userRelatedState.language,
availableLanguages,
preferredLanguages: state.osmConnection.userDetails.map(
(ud) => ud?.languages ?? [],
),
})
}
}
class DisabledQuestions extends SpecialVisualizationSvelte {
funcName = "disabled_questions"
group = "settings"
docs = "Shows which questions are disabled for every layer. Used in 'settings'"
needsUrls = []
args = []
constr(state) {
return new SvelteUIElement(DisabledQuestions, { state })
}
}
class GyroscopeAllTags extends SpecialVisualizationSvelte {
funcName = "gyroscope_all_tags"
group = "settings"
docs = "Shows the current tags of the GPS-representing object, used for debugging"
args = []
constr(): SvelteUIElement {
return new SvelteUIElement(OrientationDebugPanel, {})
}
}
class GpsAllTags extends SpecialVisualizationSvelte {
funcName = "gps_all_tags"
group = "settings"
docs = "Shows the current tags of the GPS-representing object, used for debugging"
args = []
constr(state: SpecialVisualizationState): SvelteUIElement {
const tags = (<ThemeViewState>(
state
)).geolocation.currentUserLocation.features.map(
(features) => features[0]?.properties,
)
return new SvelteUIElement(AllTagsPanel, {
state,
tags,
})
}
}
class StorageAlLTags extends SpecialVisualizationSvelte {
funcName = "storage_all_tags"
group = "settings"
docs = "Shows the current state of storage"
args = []
constr(state: SpecialVisualizationState): SvelteUIElement {
const data = {}
for (const key in localStorage) {
data[key] = localStorage[key]
}
const tags = new UIEventSource(data)
navigator.storage.estimate().then((estimate) => {
data["__usage:current:bytes"] = estimate.usage
data["__usage:current:human"] = Utils.toHumanByteSize(estimate.usage)
data["__usage:quota:bytes"] = estimate.quota
data["__usage:quota:human"] = Utils.toHumanByteSize(estimate.quota)
tags.ping()
})
return new SvelteUIElement(AllTagsPanel, { state, tags })
}
}
export class ClearCachesVis extends SpecialVisualizationSvelte {
funcName = "clear_caches"
docs = "A button which clears the locally downloaded data and the service worker. Login status etc will be kept"
args = [
{
name: "text",
required: true,
doc: "The text to show on the button",
},
]
group = "settings"
constr(
_: SpecialVisualizationState,
__: UIEventSource<Record<string, string>>,
argument: string[],
): SvelteUIElement {
return new SvelteUIElement(ClearCaches, {
msg: argument[0] ?? "Clear local caches",
})
}
}
class LoginButtonVis extends SpecialVisualizationSvelte {
funcName = "login_button"
args = [
{
name: "force",
doc: "Always show this button, even if logged in",
},
{
name: "message",
doc: "Message to display on the button",
},
]
docs = "Show a login button"
group = "settings"
constr(state: SpecialVisualizationState, _, args): SvelteUIElement {
const force = args[0].toLowerCase()
let msg = args[1]
if (msg === "") {
msg = undefined
}
return new SvelteUIElement(LoginButton, {
osmConnection: state.osmConnection,
msg,
forceShow: force === "yes" || force === "true",
})
}
}
class QrLogin extends SpecialVisualizationSvelte {
funcName = "qr_login"
args = [
{
name: "text",
doc: "Extra text on the side of the QR-code",
},
{
name: "textClass",
doc: "CSS class of the the side text",
},
]
docs = "A QR-code which shares the current URL and adds the login token. Anyone with this login token will have the same permissions as you currently have. Logging out from this session will also log them out"
group = "settings"
constr(
state: SpecialVisualizationState,
tags: UIEventSource<Record<string, string>>,
argument: string[],
feature: Feature,
layer: LayerConfig,
): SvelteUIElement {
const shared_oauth_cookie = state.osmConnection.getToken()
const sideText = argument[0]
const sideTextClass = argument[1] ?? ""
return new SvelteUIElement(QrCode, {
state,
tags,
sideText,
sideTextClass,
extraUrlParams: { shared_oauth_cookie },
})
}
}
class Logout extends SpecialVisualizationSvelte {
funcName = "logout"
args = []
needsUrls = [Constants.osmAuthConfig.url]
docs = "Shows a button where the user can log out"
group = "settings"
constr(state: SpecialVisualizationState): SvelteUIElement {
return new SvelteUIElement(LogoutButton, { osmConnection: state.osmConnection })
}
}
class PendingChanges extends SpecialVisualizationSvelte {
funcName = "pending_changes"
docs = "A module showing the pending changes, with the option to clear the pending changes"
group = "settings"
args = []
constr(state: SpecialVisualizationState): SvelteUIElement {
return new SvelteUIElement(PendingChangesIndicator, { state, compact: false })
}
}
class ClearLocationHistoryVis extends SpecialVisualizationSvelte {
group= "settings"
funcName = "clear_location_history"
docs = "A button to remove the travelled track information from the device"
args = []
constr(state) {
return new SvelteUIElement(ClearGPSHistory, { state })
}
}
export class SettingsVisualisations {
public static initList(): SpecialVisualizationSvelte[] {
return [
{
funcName: "language_picker",
args: [],
group: "settings",
docs: "A component to set the language of the user interface",
constr(state: SpecialVisualizationState): SvelteUIElement {
const availableLanguages = Locale.showLinkToWeblate.map((showTranslations) =>
showTranslations
? LanguageUtils.usedLanguagesSorted
: state?.theme?.language ?? LanguageUtils.usedLanguagesSorted
)
return new SvelteUIElement(LanguagePicker, {
assignTo: state.userRelatedState.language,
availableLanguages,
preferredLanguages: state.osmConnection.userDetails.map(
(ud) => ud?.languages ?? []
),
})
},
},
new LanguagePickerVis(),
{
funcName: "disabled_questions",
group: "settings",
docs: "Shows which questions are disabled for every layer. Used in 'settings'",
needsUrls: [],
args: [],
constr(state) {
return new SvelteUIElement(DisabledQuestions, { state })
},
},
{
funcName: "gyroscope_all_tags",
group: "settings",
docs: "Shows the current tags of the GPS-representing object, used for debugging",
args: [],
constr(): SvelteUIElement {
return new SvelteUIElement(OrientationDebugPanel, {})
},
},
{
funcName: "gps_all_tags",
group: "settings",
docs: "Shows the current tags of the GPS-representing object, used for debugging",
args: [],
constr(state: SpecialVisualizationState): SvelteUIElement {
const tags = (<ThemeViewState>(
state
)).geolocation.currentUserLocation.features.map(
(features) => features[0]?.properties
)
return new SvelteUIElement(AllTagsPanel, {
state,
tags,
})
},
},
{
funcName: "storage_all_tags",
group: "settings",
docs: "Shows the current state of storage",
args: [],
constr: function (state: SpecialVisualizationState): SvelteUIElement {
const data = {}
for (const key in localStorage) {
data[key] = localStorage[key]
}
const tags = new UIEventSource(data)
navigator.storage.estimate().then((estimate) => {
data["__usage:current:bytes"] = estimate.usage
data["__usage:current:human"] = Utils.toHumanByteSize(estimate.usage)
data["__usage:quota:bytes"] = estimate.quota
data["__usage:quota:human"] = Utils.toHumanByteSize(estimate.quota)
tags.ping()
})
return new SvelteUIElement(AllTagsPanel, { state, tags })
},
},
{
funcName: "clear_caches",
docs: "A button which clears the locally downloaded data and the service worker. Login status etc will be kept",
args: [
{
name: "text",
required: true,
doc: "The text to show on the button",
},
],
group: "settings",
constr(
_: SpecialVisualizationState,
__: UIEventSource<Record<string, string>>,
argument: string[]
): SvelteUIElement {
return new SvelteUIElement(ClearCaches, {
msg: argument[0] ?? "Clear local caches",
})
},
},
{
funcName: "login_button",
args: [
{
name: "force",
doc: "Always show this button, even if logged in",
},
{
name: "message",
doc: "Message to display on the button",
},
],
docs: "Show a login button",
needsUrls: [],
group: "settings",
constr(state: SpecialVisualizationState, _, args): SvelteUIElement {
const force = args[0].toLowerCase()
let msg = args[1]
if (msg === "") {
msg = undefined
}
return new SvelteUIElement(LoginButton, {
osmConnection: state.osmConnection,
msg,
forceShow: force === "yes" || force === "true",
})
},
},
{
funcName: "qr_login",
args: [
{
name: "text",
doc: "Extra text on the side of the QR-code",
},
{
name: "textClass",
doc: "CSS class of the the side text",
},
],
docs: "A QR-code which shares the current URL and adds the login token. Anyone with this login token will have the same permissions as you currently have. Logging out from this session will also log them out",
group: "settings",
constr(
state: SpecialVisualizationState,
tags: UIEventSource<Record<string, string>>,
argument: string[],
feature: Feature,
layer: LayerConfig
): SvelteUIElement {
const shared_oauth_cookie = state.osmConnection.getToken()
const sideText = argument[0]
const sideTextClass = argument[1] ?? ""
return new SvelteUIElement(QrCode, {
state,
tags,
sideText,
sideTextClass,
extraUrlParams: { shared_oauth_cookie },
})
},
},
{
funcName: "logout",
args: [],
needsUrls: [Constants.osmAuthConfig.url],
docs: "Shows a button where the user can log out",
group: "settings",
constr(state: SpecialVisualizationState): SvelteUIElement {
return new SvelteUIElement(LogoutButton, { osmConnection: state.osmConnection })
},
},
{
funcName: "pending_changes",
docs: "A module showing the pending changes, with the option to clear the pending changes",
group: "settings",
args: [],
constr(state: SpecialVisualizationState): SvelteUIElement {
return new SvelteUIElement(PendingChangesIndicator, { state, compact: false })
},
},
new DisabledQuestions(),
new GyroscopeAllTags(),
new GpsAllTags(),
new StorageAlLTags(),
new ClearCachesVis(),
new LoginButtonVis(),
new QrLogin(),
new Logout(),
new PendingChanges(),
new ClearLocationHistoryVis()
]
}
}