UI(Reviews): move 'loading allowed' to FeatureReviews

This commit is contained in:
Pieter Vander Vennet 2025-07-25 15:39:59 +02:00
parent ce3a049d9d
commit d662bc2707
10 changed files with 105 additions and 63 deletions

View file

@ -369,7 +369,7 @@ export default class UserRelatedState {
private static initUserSettingsState(): LayerConfig {
try {
return new LayerConfig(<LayerConfigJson>usersettings, "userinformationpanel")
return new LayerConfig(<LayerConfigJson><any>usersettings, "userinformationpanel")
} catch (e) {
return undefined
}
@ -655,7 +655,7 @@ export default class UserRelatedState {
for (const key in featureSwitches) {
if (featureSwitches[key].addCallbackAndRun) {
featureSwitches[key].addCallbackAndRun((v) => {
featureSwitches[key].addCallbackAndRun((v: string) => {
const oldV = amendedPrefs.data["__" + key]
if (oldV === v) {
return

View file

@ -4,6 +4,17 @@ import { Utils } from "../../Utils"
import { Feature, Position } from "geojson"
import { GeoOperations } from "../GeoOperations"
import { SpecialVisualizationState } from "../../UI/SpecialVisualization"
import { WithUserRelatedState } from "../../Models/ThemeViewState/WithUserRelatedState"
export interface ReviewCollection {
readonly subjectUri?: Store<string>
readonly loadingAllowed: UIEventSource<boolean>
removeReviewLocally(review: Review): void
deleteReview(review: Review & { signature: string }): Promise<void>
createReview(review: Omit<Review, "sub">): Promise<void>
}
export class MangroveIdentity {
private readonly keypair: UIEventSource<CryptoKeyPair> = new UIEventSource<CryptoKeyPair>(
@ -134,12 +145,13 @@ export class MangroveIdentity {
}
}
/**
* Tracks all reviews of a given feature, allows to create a new review (and inserts this into the list)
*
* This object will start fetching the reviews as soon as it is constructed
*/
export default class FeatureReviews {
export default class FeatureReviews implements ReviewCollection {
/**
* See https://gitlab.com/open-reviews/mangrove/-/blob/master/servers/reviewer/src/review.rs#L269 and https://source.mapcomplete.org/MapComplete/MapComplete/issues/1775
*/
@ -147,10 +159,11 @@ export default class FeatureReviews {
private static readonly _featureReviewsCache: Record<string, FeatureReviews> = {}
public readonly subjectUri: Store<string>
public readonly average: Store<number | null>
public readonly loadingAllowed: UIEventSource<boolean>
private readonly _reviews: UIEventSource<
(Review & { kid: string; signature: string; madeByLoggedInUser: Store<boolean> })[]
> = new UIEventSource(undefined)
public readonly reviews: Store<(Review & { signature: string, madeByLoggedInUser: Store<boolean> })[]> =
public readonly reviews: Store<(Review & { kid: string, signature: string, madeByLoggedInUser: Store<boolean> })[]> =
this._reviews
private readonly _lat: number
private readonly _lon: number
@ -158,23 +171,21 @@ export default class FeatureReviews {
private readonly _name: Store<string>
private readonly _identity: MangroveIdentity
private readonly _testmode: Store<boolean>
public readonly loadingAllowed: UIEventSource<boolean | null>
private readonly _reportError: (msg: string, extra: string) => Promise<void>
private constructor(
feature: Feature,
tagsSource: UIEventSource<Record<string, string>>,
mangroveIdentity: MangroveIdentity,
loadingAllowed?: UIEventSource<boolean>,
options?: Readonly<{
nameKey?: "name" | string
fallbackName?: string
uncertaintyRadius?: number
uncertaintyRadius?: number,
}>,
testmode?: Store<boolean>,
loadingAllowed?: UIEventSource<boolean | null>,
reportError?: (msg: string, extra: string) => Promise<void>
) {
this.loadingAllowed = loadingAllowed
this._reportError = reportError
const centerLonLat = GeoOperations.centerpointCoordinates(feature)
;[this._lon, this._lat] = centerLonLat
@ -221,14 +232,17 @@ export default class FeatureReviews {
})
this.subjectUri = this.ConstructSubjectUri()
this.loadingAllowed = loadingAllowed
this.subjectUri.mapD(
async (sub) => {
if (!loadingAllowed.data) {
return
}
const reviews = await MangroveReviews.getReviews({ sub })
console.debug("Got reviews for", feature, reviews, sub)
this.addReviews(reviews.reviews, this._name.data)
},
[this._name]
[this._name, loadingAllowed]
)
/* We also construct all subject queries _without_ encoding the name to work around a previous bug
* See https://github.com/giggls/opencampsitemap/issues/30
@ -267,6 +281,7 @@ export default class FeatureReviews {
})
}
/**
* Construct a featureReviewsFor or fetches it from the cache
*
@ -288,7 +303,7 @@ export default class FeatureReviews {
tagsSource: UIEventSource<Record<string, string>>,
mangroveIdentity: MangroveIdentity,
options: { nameKey: string; fallbackName: string },
state?: SpecialVisualizationState
state?: SpecialVisualizationState & WithUserRelatedState,
): FeatureReviews {
const key =
feature.properties.id +
@ -300,34 +315,14 @@ export default class FeatureReviews {
if (cached !== undefined) {
return cached
}
const themeIsSensitive = state?.theme?.enableMorePrivacy ?? false
const settings =
state?.osmConnection?.getPreference<"always" | "yes" | "ask" | "hidden">(
"reviews-allowed"
) ?? new ImmutableStore("yes")
const loadingAllowed = new UIEventSource(false)
settings.addCallbackAndRun((s) => {
if (s === "hidden") {
loadingAllowed.set(null)
return
}
if (s === "always") {
loadingAllowed.set(true)
return
}
if (themeIsSensitive || s === "ask") {
loadingAllowed.set(false)
return
}
loadingAllowed.set(true)
})
const featureReviews = new FeatureReviews(
feature,
tagsSource,
mangroveIdentity,
new UIEventSource(state?.loadReviews?.data ?? true),
options,
state?.featureSwitchIsTesting,
loadingAllowed,
(msg, extra) => state?.reportError(msg, extra)
)
FeatureReviews._featureReviewsCache[key] = featureReviews
@ -458,7 +453,7 @@ export default class FeatureReviews {
this.removeReviewLocally(review)
}
public removeReviewLocally(review: Review){
public removeReviewLocally(review: Review): void {
this._reviews.set(
this._reviews.data?.filter(r => r !== review)
)