From 40369a012bc0c94020778e4bb4efa0f132fa80ae Mon Sep 17 00:00:00 2001 From: Pieter Vander Vennet Date: Wed, 4 Jun 2025 01:20:02 +0200 Subject: [PATCH 01/17] UI: reverse top headers, make height smaller --- .../Visualisation/RegularOpeningHoursTable.svelte | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/UI/OpeningHours/Visualisation/RegularOpeningHoursTable.svelte b/src/UI/OpeningHours/Visualisation/RegularOpeningHoursTable.svelte index 77351216af..6a0fca6a54 100644 --- a/src/UI/OpeningHours/Visualisation/RegularOpeningHoursTable.svelte +++ b/src/UI/OpeningHours/Visualisation/RegularOpeningHoursTable.svelte @@ -41,6 +41,7 @@ changeHours: number[] changeTexts: string[] }[] = OH.partitionOHForDistance(changeHours, changeHourText) + weekdayHeaders.reverse(/* inplace reverse */) const weekendDayHeaders: { changeHours: number[] changeTexts: string[] @@ -91,7 +92,7 @@ {#each weekdayHeaders as weekdayHeader} - + - + Date: Wed, 4 Jun 2025 01:20:40 +0200 Subject: [PATCH 02/17] Scripts: fix runs-on --- .forgejo/workflows/daily_data_maintenance.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.forgejo/workflows/daily_data_maintenance.yml b/.forgejo/workflows/daily_data_maintenance.yml index b494d876e0..6ad98ffb40 100644 --- a/.forgejo/workflows/daily_data_maintenance.yml +++ b/.forgejo/workflows/daily_data_maintenance.yml @@ -22,7 +22,7 @@ jobs: ssh hetzner "cd data && rm -rf community-index/ && unzip community-index.zip && rm community-index.zip" update_statistics: - runs-on: [ ubuntu-latest, hetzner-access ] + runs-on: [ hetzner-access ] steps: - uses: https://source.mapcomplete.org/actions/checkout@v4 - uses: ./.forgejo/setup From fe39817d14f5ccedf0cdb57c7c8959e4c54d1528 Mon Sep 17 00:00:00 2001 From: Pieter Vander Vennet Date: Wed, 4 Jun 2025 18:39:15 +0200 Subject: [PATCH 03/17] Scripts: improve documentation and try to speed up things --- .forgejo/workflows/update_database.yml | 4 +- Docs/SettingUpPSQL.md | 10 ++- scripts/generateLayouts.ts | 91 ++++++++++++-------------- 3 files changed, 53 insertions(+), 52 deletions(-) diff --git a/.forgejo/workflows/update_database.yml b/.forgejo/workflows/update_database.yml index 360c0d7f3f..39ed860920 100644 --- a/.forgejo/workflows/update_database.yml +++ b/.forgejo/workflows/update_database.yml @@ -5,7 +5,7 @@ on: jobs: - daily_data_maintenance: + update_database: runs-on: [ osm-cache ] steps: - uses: https://source.mapcomplete.org/actions/checkout@v4 @@ -20,7 +20,7 @@ jobs: run: npm run build:dbscript # output: build_db.lua - - name: Print planet file date + - name: Create and fill database shell: bash run: | # LAIN has a weekly updated planet file in /data/planet-latest.osm.pbf diff --git a/Docs/SettingUpPSQL.md b/Docs/SettingUpPSQL.md index e30bfead2d..7aaafb89f0 100644 --- a/Docs/SettingUpPSQL.md +++ b/Docs/SettingUpPSQL.md @@ -1,13 +1,19 @@ # Setting up a synced OSM-server for quick layer access +## Requirements + +Debian machine (e.g. Ubuntu) + +`apt install osmium-tool docker.io osm2pgsql` + ## Setting up the SQL-server (only once): `sudo docker run --name some-postgis -e POSTGRES_PASSWORD=password -e POSTGRES_USER=user -d -p 5444:5432 -v ~/data/pgsql/:/var/lib/postgresql/data postgis/postgis` Increase the max number of connections. osm2pgsql needs connection one per table (and a few more), and since we are making one table per layer in MapComplete, this amounts to a lot. -- Open PGAdmin, open the PGSQL-tool (CLI-button at the top); alternativly: psql --host=172.17.0.1 --port=5444 - --user=user +- Open PGAdmin, open the PGSQL-tool (CLI-button at the top); alternativly: + `psql --host=172.17.0.1 --port=5444 --user=user` - Run `show config_file;` to get the config file location (in docker). This is probably `/var/lib/postgresql/data/postgresql.conf` - In a terminal, run `sudo docker exec -i bash` (run `sudo docker ps` to get the container id) diff --git a/scripts/generateLayouts.ts b/scripts/generateLayouts.ts index 522f86f790..cb34462412 100644 --- a/scripts/generateLayouts.ts +++ b/scripts/generateLayouts.ts @@ -40,7 +40,7 @@ class GenerateLayouts extends Script { private eliUrlsCached: string[] private date = new Date().toISOString() private branchName: string = undefined - + private alreadyWritten: Set = new Set() constructor() { super("Generates an '.html' and 'index_.ts' for every theme") } @@ -70,7 +70,7 @@ class GenerateLayouts extends Script { }) } - async createIcon(iconPath: string, size: number, alreadyWritten: string[]) { + async createIcon(iconPath: string, size: number) { let name = iconPath.split(".").slice(0, -1).join(".") // drop svg suffix if (name.startsWith("./")) { name = name.substring(2) @@ -78,10 +78,10 @@ class GenerateLayouts extends Script { const newname = `assets/generated/images/${name.replace(/\//g, "_")}${size}.png` const targetpath = `public/${newname}` - if (alreadyWritten.indexOf(newname) >= 0) { + if (this.alreadyWritten.has(newname)) { return newname } - alreadyWritten.push(newname) + this.alreadyWritten.add(newname) if (existsSync(targetpath)) { return newname } @@ -163,8 +163,7 @@ class GenerateLayouts extends Script { } async createManifest( - layout: ThemeConfig, - alreadyWritten: string[] + layout: ThemeConfig ): Promise<{ manifest: any whiteIcons: string[] @@ -199,8 +198,8 @@ class GenerateLayouts extends Script { const sizes = [72, 96, 120, 128, 144, 152, 180, 192, 384, 512] for (const size of sizes) { - const name = await this.createIcon(path, size, alreadyWritten) - const whiteIcon = await this.createIcon(whiteBackgroundPath, size, alreadyWritten) + const name = await this.createIcon(path, size) + const whiteIcon = await this.createIcon(whiteBackgroundPath, size) whiteIcons.push(whiteIcon) icons.push({ src: name, @@ -447,8 +446,7 @@ class GenerateLayouts extends Script { async createLandingPage( layout: ThemeConfig, layoutJson: ThemeConfigJson, - whiteIcons, - alreadyWritten + whiteIcons ) { Locale.language.setData(layout.language[0]) const targetLanguage = layout.language[0] @@ -471,7 +469,7 @@ class GenerateLayouts extends Script { if (twitterImage.endsWith(".svg")) { try { // svgs are badly supported as social image, we use a generated svg instead - twitterImage = await this.createIcon(twitterImage, 512, alreadyWritten) + twitterImage = await this.createIcon(twitterImage, 512) } catch (e) { console.error("Could not generate image:", e) } @@ -479,7 +477,7 @@ class GenerateLayouts extends Script { if (ogImage.endsWith(".svg")) { try { - ogImage = await this.createIcon(ogImage, 512, alreadyWritten) + ogImage = await this.createIcon(ogImage, 512) } catch (e) { console.error("Could not generate image:", e) } @@ -611,64 +609,62 @@ class GenerateLayouts extends Script { } } + private async createThemeFor(layoutConfigJson: ThemeConfigJson) { + const layout = new ThemeConfig(layoutConfigJson, true) + const layoutName = layout.id + + const err = (err) => { + if (err !== null) { + console.log("Could not write manifest for ", layoutName, " because ", err) + } + } + const { manifest, whiteIcons } = await this.createManifest(layout) + const manif = JSON.stringify(manifest, undefined, 2) + const manifestLocation = encodeURIComponent(layout.id.toLowerCase()) + ".webmanifest" + writeFile("public/" + manifestLocation, manif, err) + + // Create a landing page for the given theme + const landing = await this.createLandingPage( + layout, + layoutConfigJson, + whiteIcons + ) + + writeFile(this.enc(layout.id) + ".html", landing, err) + await this.createIndexFor(layout) + } + async main(): Promise { - const alreadyWritten = [] this.createDir("./public/assets/") this.createDir("./public/assets/generated") this.createDir("./public/assets/generated/images") - const blacklist = [ + const blacklist = new Set([ "", "test", ".", "..", "manifest", "index", + "inspector", "land", "preferences", "account", "openstreetmap", "custom", "theme", - ] + ]) const args = process.argv const theme = args[2] if (theme !== undefined) { console.warn("Only generating layout " + theme) } const paths = ScriptUtils.readDirRecSync("./public/assets/generated/themes/", 1) - for (const i in paths) { - const layoutConfigJson = JSON.parse(readFileSync(paths[i], "utf8")) - if (theme !== undefined && layoutConfigJson.id !== theme) { - continue - } - const layout = new ThemeConfig(layoutConfigJson, true) - const layoutName = layout.id - if (blacklist.indexOf(layoutName.toLowerCase()) >= 0) { - console.log(`Skipping a layout with name ${layoutName}, it is on the blacklist`) - continue - } - const err = (err) => { - if (err !== null) { - console.log("Could not write manifest for ", layoutName, " because ", err) - } - } - const { manifest, whiteIcons } = await this.createManifest(layout, alreadyWritten) - const manif = JSON.stringify(manifest, undefined, 2) - const manifestLocation = encodeURIComponent(layout.id.toLowerCase()) + ".webmanifest" - writeFile("public/" + manifestLocation, manif, err) + const configs = paths.map(path => JSON.parse(readFileSync(path, "utf8"))) + const configsFiltered = configs + .filter(config => (theme !== undefined && config.id === theme) || !blacklist.has(config.id)) - // Create a landing page for the given theme - const landing = await this.createLandingPage( - layout, - layoutConfigJson, - whiteIcons, - alreadyWritten - ) - - writeFile(this.enc(layout.id) + ".html", landing, err) - await this.createIndexFor(layout) - } + await Promise.all(configsFiltered.map(config => this.createThemeFor(config))) const { manifest } = await this.createManifest( new ThemeConfig({ @@ -681,8 +677,7 @@ class GenerateLayouts extends Script { startZoom: 0, title: { en: "MapComplete" }, description: { en: "A thematic map viewer and editor based on OpenStreetMap" }, - }), - alreadyWritten + }) ) const manif = JSON.stringify(manifest, undefined, 2) From 9725e98e6f17c58aac07524371529e077917ee42 Mon Sep 17 00:00:00 2001 From: Pieter Vander Vennet Date: Wed, 4 Jun 2025 21:15:53 +0200 Subject: [PATCH 04/17] Fix: extract goatcounter to update hash --- 404.html | 4 +--- index.html | 4 +--- inspector.html | 4 +--- privacy.html | 4 +--- src/loadGoatcounter.js | 7 +++++++ statistics.html | 4 +--- status.html | 4 +--- studio.html | 4 +--- test/CodeQuality.spec.ts | 10 +++++++++- theme.html | 4 +--- 10 files changed, 24 insertions(+), 25 deletions(-) create mode 100644 src/loadGoatcounter.js diff --git a/404.html b/404.html index a7924c5298..f0273dc52e 100644 --- a/404.html +++ b/404.html @@ -41,9 +41,7 @@
- + diff --git a/index.html b/index.html index 0743235f0a..626628eda2 100644 --- a/index.html +++ b/index.html @@ -42,9 +42,7 @@
- + diff --git a/inspector.html b/inspector.html index 25d0712d7e..0c458e9444 100644 --- a/inspector.html +++ b/inspector.html @@ -12,9 +12,7 @@
Loading inspector...
- + diff --git a/privacy.html b/privacy.html index c6dc3b5bbd..0e8ab8bdc3 100644 --- a/privacy.html +++ b/privacy.html @@ -38,9 +38,7 @@
- + diff --git a/src/loadGoatcounter.js b/src/loadGoatcounter.js new file mode 100644 index 0000000000..314639453f --- /dev/null +++ b/src/loadGoatcounter.js @@ -0,0 +1,7 @@ +const script = document.createElement("script") +script.async = true +script.dataset.goatcounter = "https://pietervdvn.goatcounter.com/count" +script.src = "https://gc.zgo.at/count.js" +script.crossOrigin = "anonymous" +script.integrity = "sha384-atnOLvQb9t+jTSipvd75X2yginT4PjVbqDdlJAmxMm+wYElFmeR6EmLP5bYeoRVQ" +document.head.appendChild(script) diff --git a/statistics.html b/statistics.html index 0e65fa043f..935ad2a040 100644 --- a/statistics.html +++ b/statistics.html @@ -12,9 +12,7 @@
Loading statistics...
- + diff --git a/status.html b/status.html index b05d424fe4..0f1d127324 100644 --- a/status.html +++ b/status.html @@ -13,9 +13,7 @@
- + diff --git a/studio.html b/studio.html index d4f04e41aa..9624b3f0e4 100644 --- a/studio.html +++ b/studio.html @@ -19,9 +19,7 @@
- + diff --git a/test/CodeQuality.spec.ts b/test/CodeQuality.spec.ts index c2939ef0fe..2cafdcad71 100644 --- a/test/CodeQuality.spec.ts +++ b/test/CodeQuality.spec.ts @@ -158,6 +158,14 @@ describe("Code quality", () => { for (const htmlFile of htmlFiles) { await validateScriptIntegrityOf(htmlFile) } + const goatCounter = "https://gc.zgo.at/count.js" + const data: string = (await ScriptUtils.Download(goatCounter))["content"] + const hashed = await webcrypto.subtle.digest("SHA-384", new TextEncoder().encode(data)) + const hashedB64 = _arrayBufferToBase64(hashed) + const goatCounterScript = readFileSync("./src/loadGoatcounter.js", "utf-8") + if (goatCounterScript.indexOf(hashedB64) < 0) { + throw "Hash sha-384" + hashedB64 + " not found in 'loadGoatcounter.js'" + } }) /* itAsync( @@ -168,7 +176,7 @@ describe("Code quality", () => { ) ) /* - itAsync( + itAsync(int "should not contain '[\"default\"]'", detectInCode('\\[\\"default\\"\\]', "Possible leftover of faulty default import") )*/ diff --git a/theme.html b/theme.html index 05ceed9e71..1526f204b5 100644 --- a/theme.html +++ b/theme.html @@ -92,9 +92,7 @@ - + From 236d4d87da0ba8941e14dd84451673077f6f3d2a Mon Sep 17 00:00:00 2001 From: Pieter Vander Vennet Date: Thu, 5 Jun 2025 11:38:29 +0200 Subject: [PATCH 05/17] Feature: photoSphereViewer exports the currently seen image --- src/UI/Image/photoSphereViewerWrapper.ts | 34 +++++++++++++++--------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/src/UI/Image/photoSphereViewerWrapper.ts b/src/UI/Image/photoSphereViewerWrapper.ts index bdbfb6f64e..fc31fd90e7 100644 --- a/src/UI/Image/photoSphereViewerWrapper.ts +++ b/src/UI/Image/photoSphereViewerWrapper.ts @@ -3,18 +3,26 @@ import "pannellum" import { Feature, Geometry, Point } from "geojson" import { GeoOperations } from "../../Logic/GeoOperations" import { HotspotProperties, PanoramaView } from "../../Logic/ImageProviders/ImageProvider" +import { Store, UIEventSource } from "../../Logic/UIEventSource" export class PhotoSphereViewerWrapper { - private imageInfo: Feature + private _imageInfo: UIEventSource>> = new UIEventSource(undefined) + public imageInfo: Store>> = this._imageInfo private readonly viewer: Pannellum.Viewer private nearbyFeatures: Feature[] = [] + /** + * + * @param container The HTML-element to bind to + * @param imageInfo An eventSource containing the panorama-info. Might be changed by this component if walking around; + * @param nearbyFeatures Nearby features to show a point about, e.g. to walk around + */ constructor( container: HTMLElement, imageInfo: Feature, nearbyFeatures?: Feature[] ) { - this.imageInfo = imageInfo + this._imageInfo.set(imageInfo) this.viewer = pannellum.viewer(container, { default: { firstScene: imageInfo.properties.url, @@ -31,16 +39,17 @@ export class PhotoSphereViewerWrapper { compass: true, showControls: false, northOffset: imageInfo.properties.northOffset, - horizonPitch: imageInfo.properties.pitchOffset, + horizonPitch: imageInfo.properties.pitchOffset }, }, }) this.setNearbyFeatures(nearbyFeatures) + } public calculatePitch(feature: Feature): number { - const coors = this.imageInfo.geometry.coordinates + const coors = this.imageInfo.data.geometry.coordinates const distance = GeoOperations.distanceBetween( coors, GeoOperations.centerpointCoordinates(feature) @@ -72,7 +81,6 @@ export class PhotoSphereViewerWrapper { return } this.clearHotspots() - this.imageInfo = imageInfo this.viewer.addScene(imageInfo.properties.url, { panorama: imageInfo.properties.url, northOffset: imageInfo.properties.northOffset, @@ -82,27 +90,29 @@ export class PhotoSphereViewerWrapper { this.viewer.loadScene(imageInfo.properties.url, 0, imageInfo.properties.northOffset) this.setNearbyFeatures(this.nearbyFeatures) + this._imageInfo.set(imageInfo) + } private clearHotspots() { - const hotspots = - this.viewer.getConfig()["scenes"][this.imageInfo.properties.url].hotSpots ?? [] + const currentUrl = this.imageInfo.data.properties.url + const hotspots = this.viewer.getConfig()["scenes"][currentUrl].hotSpots ?? [] for (const hotspot of hotspots) { - this.viewer.removeHotSpot(hotspot?.id, this.imageInfo.properties.url) + this.viewer.removeHotSpot(hotspot?.id, currentUrl) } } public setNearbyFeatures(nearbyFeatures: Feature[]) { - const imageInfo = this.imageInfo + const imageInfo = this.imageInfo.data if (!this.imageInfo) { return } const northOffs = imageInfo.properties.northOffset this.nearbyFeatures = nearbyFeatures this.clearHotspots() - const centralImageLocation = this.imageInfo.geometry.coordinates + const centralImageLocation = imageInfo.geometry.coordinates for (const f of nearbyFeatures ?? []) { - if (f.properties.gotoPanorama?.properties?.url === this.imageInfo.properties.url) { + if (f.properties.gotoPanorama?.properties?.url === imageInfo.properties.url) { continue // This is the current panorama, no need to show it } const yaw = GeoOperations.bearing(imageInfo, GeoOperations.centerpoint(f)) @@ -128,7 +138,7 @@ export class PhotoSphereViewerWrapper { this.setPanorama(f.properties.gotoPanorama) }, }, - this.imageInfo.properties.url + imageInfo.properties.url ) if (f.properties.focus) { this.viewer.setYaw(yaw - northOffs) From b269d210bba5933b6e54b493eb9414d827eb5086 Mon Sep 17 00:00:00 2001 From: Pieter Vander Vennet Date: Thu, 5 Jun 2025 11:40:56 +0200 Subject: [PATCH 06/17] Feature: add provider to photosphereview --- src/Logic/ImageProviders/ImageProvider.ts | 3 ++- src/Logic/ImageProviders/Mapillary.ts | 2 ++ src/Logic/ImageProviders/Panoramax.ts | 8 +++++--- src/Logic/Web/NearbyImagesSearch.ts | 17 +++++++++-------- src/UI/Image/NearbyImages.svelte | 1 + 5 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/Logic/ImageProviders/ImageProvider.ts b/src/Logic/ImageProviders/ImageProvider.ts index 99b23f01b3..8d9f8df17b 100644 --- a/src/Logic/ImageProviders/ImageProvider.ts +++ b/src/Logic/ImageProviders/ImageProvider.ts @@ -36,6 +36,7 @@ export interface PanoramaView { */ northOffset?: number pitchOffset?: number + provider: ImageProvider | string } /** @@ -124,7 +125,7 @@ export default abstract class ImageProvider { public abstract DownloadAttribution(providedImage: { url: string - id: string + id?: string }): Promise public abstract apiUrls(): string[] diff --git a/src/Logic/ImageProviders/Mapillary.ts b/src/Logic/ImageProviders/Mapillary.ts index 64b477bd6c..44b95ec55e 100644 --- a/src/Logic/ImageProviders/Mapillary.ts +++ b/src/Logic/ImageProviders/Mapillary.ts @@ -169,6 +169,8 @@ export class Mapillary extends ImageProvider { properties: { url: response.thumb_2048_url, northOffset: response.computed_compass_angle, + provider: this, + imageMeta: image }, } } diff --git a/src/Logic/ImageProviders/Panoramax.ts b/src/Logic/ImageProviders/Panoramax.ts index 4bcf26742d..3494c563a2 100644 --- a/src/Logic/ImageProviders/Panoramax.ts +++ b/src/Logic/ImageProviders/Panoramax.ts @@ -208,8 +208,8 @@ export default class PanoramaxImageProvider extends ImageProvider { } public async DownloadAttribution(providedImage: { - url: string - id: string + id: string, + url: string // Actually not used }): Promise { const meta = await this.getInfoFor(providedImage.id) @@ -245,10 +245,12 @@ export default class PanoramaxImageProvider extends ImageProvider { return >{ type: "Feature", geometry: imageInfo.geometry, - properties: { + properties: { url, northOffset, pitchOffset, + provider: this, + imageMeta: imageInfo }, } } diff --git a/src/Logic/Web/NearbyImagesSearch.ts b/src/Logic/Web/NearbyImagesSearch.ts index 7e32404093..3bcb1de3a9 100644 --- a/src/Logic/Web/NearbyImagesSearch.ts +++ b/src/Logic/Web/NearbyImagesSearch.ts @@ -17,7 +17,7 @@ interface ImageFetcher { * @param lat * @param lon */ - fetchImages(lat: number, lon: number): Promise + fetchImages(lat: number, lon: number): Promise<(P4CPicture & { id: string })[]> readonly name: string } @@ -25,7 +25,7 @@ interface ImageFetcher { class CachedFetcher implements ImageFetcher { private readonly _fetcher: ImageFetcher private readonly _zoomlevel: number - private readonly cache: Map> = new Map< + private readonly cache: Map> = new Map< number, Promise >() @@ -37,7 +37,7 @@ class CachedFetcher implements ImageFetcher { this.name = fetcher.name } - fetchImages(lat: number, lon: number): Promise { + fetchImages(lat: number, lon: number): Promise<(P4CPicture & { id: string })[]> { const tile = Tiles.embedded_tile(lat, lon, this._zoomlevel) const tileIndex = Tiles.tile_index(tile.z, tile.x, tile.y) if (this.cache.has(tileIndex)) { @@ -80,7 +80,7 @@ class NearbyImageUtils { } class P4CImageFetcher implements ImageFetcher { - public static readonly services = ["mapillary", "flickr", "kartaview", "wikicommons"] as const + public static readonly services = ["flickr", "kartaview", "wikicommons"] as const public static readonly apiUrls = ["https://api.flickr.com"] private _options: { maxDaysOld: number; searchRadius: number } public readonly name: P4CService @@ -90,7 +90,7 @@ class P4CImageFetcher implements ImageFetcher { this._options = options } - async fetchImages(lat: number, lon: number): Promise { + async fetchImages(lat: number, lon: number): Promise<(P4CPicture & { id: string })[]> { const picManager = new P4C.PicturesManager({ usefetchers: [this.name] }) const maxAgeSeconds = (this._options?.maxDaysOld ?? 3 * 365) * 24 * 60 * 60 * 1000 const searchRadius = this._options?.searchRadius ?? 100 @@ -272,7 +272,7 @@ class MapillaryFetcher implements ImageFetcher { this.end_captured_at = options?.end_captured_at } - async fetchImages(lat: number, lon: number): Promise { + async fetchImages(lat: number, lon: number): Promise<(P4CPicture & { id: string })[]> { const boundingBox = new BBox([[lon, lat]]).padAbsolute(0.003) let url = "https://graph.mapillary.com/images?fields=geometry,computed_geometry,creator,id,captured_at,thumb_256_url,thumb_original_url,compass_angle&bbox=" + @@ -313,7 +313,7 @@ class MapillaryFetcher implements ImageFetcher { captured_at: number }[] }>(url) - const pics: P4CPicture[] = [] + const pics: (P4CPicture & { id: string })[] = [] for (const img of response.data) { const c = img.computed_geometry?.coordinates ?? img.geometry.coordinates if (img.thumb_original_url === undefined) { @@ -322,6 +322,7 @@ class MapillaryFetcher implements ImageFetcher { const [lon, lat] = img.computed_geometry.coordinates pics.push({ pictureUrl: img.thumb_original_url, + id: img.id, provider: "Mapillary", coordinates: { lng: c[0], lat: c[1] }, thumbUrl: img.thumb_256_url, @@ -411,7 +412,7 @@ export class CombinedFetcher { lon: number, lat: number ): { - images: Store + images: Store<(P4CPicture & { provider })[]> state: Store> } { const sink = new UIEventSource([]) diff --git a/src/UI/Image/NearbyImages.svelte b/src/UI/Image/NearbyImages.svelte index 484b561690..7c1cb52dfa 100644 --- a/src/UI/Image/NearbyImages.svelte +++ b/src/UI/Image/NearbyImages.svelte @@ -68,6 +68,7 @@ northOffset: p4c.direction, rotation: p4c.direction, spherical: p4c.details.isSpherical ? "yes" : "no", + provider: p4c.provider }, } ) From 84a2ff5f54f70401bb80a43abc30b722b8c04d04 Mon Sep 17 00:00:00 2001 From: Pieter Vander Vennet Date: Thu, 5 Jun 2025 12:14:23 +0200 Subject: [PATCH 07/17] Scripts: force overwrite the database --- .forgejo/workflows/update_database.yml | 2 +- scripts/osm2pgsql/createNewDatabase.ts | 12 +++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/.forgejo/workflows/update_database.yml b/.forgejo/workflows/update_database.yml index 39ed860920..b16b80619f 100644 --- a/.forgejo/workflows/update_database.yml +++ b/.forgejo/workflows/update_database.yml @@ -29,7 +29,7 @@ jobs: DATE=$(echo $TIMESTAMP | sed "s/T.*//") echo $DATE # Create a new database in postgres - npm run create:database -- -- $DATE + npm run create:database -- -- $DATE --overwrite echo "Seeding database '$DATE'" osm2pgsql -O flex -S build_db.lua -s --flat-nodes=import-help-file -d postgresql://user:password@localhost:5444/osm-poi.${DATE} /data/planet-latest.osm.pbf npm run delete:database:old diff --git a/scripts/osm2pgsql/createNewDatabase.ts b/scripts/osm2pgsql/createNewDatabase.ts index b22aa80ef0..87ee167488 100644 --- a/scripts/osm2pgsql/createNewDatabase.ts +++ b/scripts/osm2pgsql/createNewDatabase.ts @@ -9,8 +9,18 @@ class CreateNewDatabase extends Script { } async main(args: string[]): Promise { + const targetName = args[0] + const overwrite = args[1] === "--overwrite" const db = new OsmPoiDatabase("postgresql://user:password@localhost:5444") - await db.createNew(args[0]) + const knownDatabases = await db.findSuitableDatabases() + if (knownDatabases.indexOf(targetName) > 0) { + if (overwrite) { + await db.deleteDatabase(targetName) + } else { + throw "ERROR: the target database " + targetName + " already exists" + } + } + await db.createNew(targetName) } } From a55ae9d3e8b36e7c6640b9fa9a3c503075c8addc Mon Sep 17 00:00:00 2001 From: Pieter Vander Vennet Date: Thu, 5 Jun 2025 12:17:59 +0200 Subject: [PATCH 08/17] Fix: improve typing --- src/UI/Image/LinkableImage.svelte | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/UI/Image/LinkableImage.svelte b/src/UI/Image/LinkableImage.svelte index cffa1dc024..2df9132f5b 100644 --- a/src/UI/Image/LinkableImage.svelte +++ b/src/UI/Image/LinkableImage.svelte @@ -7,10 +7,10 @@ import LinkImageAction from "../../Logic/Osm/Actions/LinkImageAction" import ChangeTagAction from "../../Logic/Osm/Actions/ChangeTagAction" import { Tag } from "../../Logic/Tags/Tag" - import type { Feature } from "geojson" + import type { Feature, Point } from "geojson" import Translations from "../i18n/Translations" import LayerConfig from "../../Models/ThemeConfig/LayerConfig" - import type { ProvidedImage } from "../../Logic/ImageProviders/ImageProvider" + import type { HotspotProperties, ProvidedImage } from "../../Logic/ImageProviders/ImageProvider" import AttributedImage from "./AttributedImage.svelte" import SpecialTranslation from "../Popup/TagRendering/SpecialTranslation.svelte" import LoginToggle from "../Base/LoginToggle.svelte" @@ -27,7 +27,7 @@ export let layer: LayerConfig export let highlighted: UIEventSource = undefined - export let nearbyFeatures: Feature[] | Store = [] + export let nearbyFeatures: Feature[] | Store[]> = [] export let linkable = true let targetValue = Object.values(image.osmTags)[0] let isLinked = new UIEventSource(Object.values(tags.data).some((v) => targetValue === v)) From d9c1fe3f74387b3e2c8a63b734c6bfafe9eb44cf Mon Sep 17 00:00:00 2001 From: Pieter Vander Vennet Date: Thu, 5 Jun 2025 12:21:17 +0200 Subject: [PATCH 09/17] UI: add download links --- src/UI/Image/ImageOperations.svelte | 30 +++++++++++++++++------------ src/UI/Image/ImagePreview.svelte | 26 +++++++++++++++++-------- 2 files changed, 36 insertions(+), 20 deletions(-) diff --git a/src/UI/Image/ImageOperations.svelte b/src/UI/Image/ImageOperations.svelte index 5d4450921b..46b8d2dd36 100644 --- a/src/UI/Image/ImageOperations.svelte +++ b/src/UI/Image/ImageOperations.svelte @@ -8,7 +8,7 @@ import type { ProvidedImage } from "../../Logic/ImageProviders/ImageProvider" import ImageAttribution from "./ImageAttribution.svelte" import ImagePreview from "./ImagePreview.svelte" - import { DownloadIcon } from "@rgossiaux/svelte-heroicons/solid" + import { DownloadIcon, ExternalLinkIcon } from "@rgossiaux/svelte-heroicons/solid" import { twMerge } from "tailwind-merge" import { UIEventSource } from "../../Logic/UIEventSource" import Loading from "../Base/Loading.svelte" @@ -23,7 +23,7 @@ export let nearbyFeatures: | Feature[] | Store[]> = [] - + let visitUrl = image.provider?.visitUrl(image) let isLoaded = new UIEventSource(false) @@ -39,22 +39,28 @@ {#if $$slots["dot-menu-actions"]} - - - + + + + {#if visitUrl !== undefined} + + + + + {/if} {/if}
- +
diff --git a/src/UI/Image/ImagePreview.svelte b/src/UI/Image/ImagePreview.svelte index f7eb0d62f8..6cc6f75479 100644 --- a/src/UI/Image/ImagePreview.svelte +++ b/src/UI/Image/ImagePreview.svelte @@ -3,24 +3,22 @@ * The image preview allows to drag and zoom in to the image */ import panzoom from "panzoom" - import type { HotspotProperties, ProvidedImage } from "../../Logic/ImageProviders/ImageProvider" - import { UIEventSource } from "../../Logic/UIEventSource" + import type { HotspotProperties, PanoramaView, ProvidedImage } from "../../Logic/ImageProviders/ImageProvider" + import ImageProvider from "../../Logic/ImageProviders/ImageProvider" + import { Store, UIEventSource } from "../../Logic/UIEventSource" import Zoomcontrol from "../Zoomcontrol" import { onDestroy } from "svelte" - import type { PanoramaView } from "../../Logic/ImageProviders/ImageProvider" import { PhotoSphereViewerWrapper } from "./photoSphereViewerWrapper" - import type { Feature, Geometry, Point } from "geojson" - import { Store } from "../../Logic/UIEventSource" + import AllImageProviders from "../../Logic/ImageProviders/AllImageProviders" export let nearbyFeatures: | Feature[] | Store[]> = [] - export let image: Partial + export let image: Partial & { url: string, id: string } let panzoomInstance = undefined let panzoomEl: HTMLElement let viewerEl: HTMLElement - export let isLoaded: UIEventSource = undefined onDestroy(Zoomcontrol.createLock()) @@ -32,10 +30,21 @@ async function initPhotosphere() { const imageInfo: Feature = await image.provider.getPanoramaInfo(image) if (imageInfo === undefined) { - console.error("Image info is apperently undefined for", image) + console.error("Image info is apparently undefined for", image) return } const viewer = new PhotoSphereViewerWrapper(viewerEl, imageInfo) + viewer.imageInfo.addCallbackAndRunD(panoramaInfo => { + let provider: ImageProvider + if (typeof panoramaInfo.properties.provider === "string") { + provider = AllImageProviders.byName(panoramaInfo.properties.provider) + } else { + provider = panoramaInfo.properties.provider + } + console.log(">>> Got:", panoramaInfo, "by", provider.name) +UI: + //actuallyDisplayed.set(image.properties.imageMeta) + }) if (Array.isArray(nearbyFeatures)) { viewer.setNearbyFeatures(nearbyFeatures) } else { @@ -77,5 +86,6 @@ isLoaded?.setData(true) }} src={image.url_hd ?? image.url} + alt="" /> {/if} From 1ddfffcee05f88966695c10619885dc411297e8a Mon Sep 17 00:00:00 2001 From: Pieter Vander Vennet Date: Thu, 5 Jun 2025 12:21:38 +0200 Subject: [PATCH 10/17] Refactoring: image providers use ID everywhere --- src/Logic/ImageProviders/ImageProvider.ts | 5 ++--- src/Logic/ImageProviders/Imgur.ts | 10 +++++----- src/Logic/ImageProviders/Panoramax.ts | 3 +-- src/Logic/ImageProviders/WikimediaImageProvider.ts | 6 +++--- src/Logic/Web/NearbyImagesSearch.ts | 14 ++++++++------ src/UI/Image/ImagePreview.svelte | 1 - 6 files changed, 19 insertions(+), 20 deletions(-) diff --git a/src/Logic/ImageProviders/ImageProvider.ts b/src/Logic/ImageProviders/ImageProvider.ts index 8d9f8df17b..d3d14b705e 100644 --- a/src/Logic/ImageProviders/ImageProvider.ts +++ b/src/Logic/ImageProviders/ImageProvider.ts @@ -124,8 +124,7 @@ export default abstract class ImageProvider { ): undefined | ProvidedImage[] | Promise public abstract DownloadAttribution(providedImage: { - url: string - id?: string + id: string }): Promise public abstract apiUrls(): string[] @@ -142,7 +141,7 @@ export default abstract class ImageProvider { id: string }): Promise> | undefined - public static async offerImageAsDownload(image: ProvidedImage) { + public static async offerImageAsDownload(image: { url_hd?: string, url: string }) { const response = await fetch(image.url_hd ?? image.url) const blob = await response.blob() Utils.offerContentsAsDownloadableFile(blob, new URL(image.url).pathname.split("/").at(-1), { diff --git a/src/Logic/ImageProviders/Imgur.ts b/src/Logic/ImageProviders/Imgur.ts index 8b18be9ff7..f7239b2cc3 100644 --- a/src/Logic/ImageProviders/Imgur.ts +++ b/src/Logic/ImageProviders/Imgur.ts @@ -75,27 +75,27 @@ export class Imgur extends ImageProvider { * * const data = {"data":{"id":"I9t6B7B","title":"Station Knokke","description":"author:Pieter Vander Vennet\r\nlicense:CC-BY 4.0\r\nosmid:node\/9812712386","datetime":1655052078,"type":"image\/jpeg","animated":false,"width":2400,"height":1795,"size":910872,"views":2,"bandwidth":1821744,"vote":null,"favorite":false,"nsfw":false,"section":null,"account_url":null,"account_id":null,"is_ad":false,"in_most_viral":false,"has_sound":false,"tags":[],"ad_type":0,"ad_url":"","edited":"0","in_gallery":false,"link":"https:\/\/i.imgur.com\/I9t6B7B.jpg","ad_config":{"safeFlags":["not_in_gallery","share"],"highRiskFlags":[],"unsafeFlags":["sixth_mod_unsafe"],"wallUnsafeFlags":[],"showsAds":false,"showAdLevel":1}},"success":true,"status":200} * Utils.injectJsonDownloadForTests("https://api.imgur.com/3/image/E0RuAK3", data) - * const licenseInfo = await Imgur.singleton.DownloadAttribution({url: "https://i.imgur.com/E0RuAK3.jpg"}) + * const licenseInfo = await Imgur.singleton.DownloadAttribution({id: "https://i.imgur.com/E0RuAK3.jpg"}) * const expected = new LicenseInfo() * expected.licenseShortName = "CC-BY 4.0" * expected.artist = "Pieter Vander Vennet" * expected.date = new Date(1655052078000) * expected.views = 2 * licenseInfo // => expected - * const licenseInfoJpeg = await Imgur.singleton.DownloadAttribution({url:"https://i.imgur.com/E0RuAK3.jpeg"}) + * const licenseInfoJpeg = await Imgur.singleton.DownloadAttribution({id:"https://i.imgur.com/E0RuAK3.jpeg"}) * licenseInfoJpeg // => expected - * const licenseInfoUpperCase = await Imgur.singleton.DownloadAttribution({url: "https://i.imgur.com/E0RuAK3.JPEG"}) + * const licenseInfoUpperCase = await Imgur.singleton.DownloadAttribution({id: "https://i.imgur.com/E0RuAK3.JPEG"}) * licenseInfoUpperCase // => expected * * */ public async DownloadAttribution( providedImage: { - url: string + id: string }, withResponse?: (obj) => void ): Promise { - const url = providedImage.url + const url = providedImage.id const hash = url.substr("https://i.imgur.com/".length).split(/(\.jpe?g)|(\.png)/i)[0] const apiUrl = "https://api.imgur.com/3/image/" + hash diff --git a/src/Logic/ImageProviders/Panoramax.ts b/src/Logic/ImageProviders/Panoramax.ts index 3494c563a2..8227c78d02 100644 --- a/src/Logic/ImageProviders/Panoramax.ts +++ b/src/Logic/ImageProviders/Panoramax.ts @@ -208,8 +208,7 @@ export default class PanoramaxImageProvider extends ImageProvider { } public async DownloadAttribution(providedImage: { - id: string, - url: string // Actually not used + id: string }): Promise { const meta = await this.getInfoFor(providedImage.id) diff --git a/src/Logic/ImageProviders/WikimediaImageProvider.ts b/src/Logic/ImageProviders/WikimediaImageProvider.ts index 3d587e5499..5d247f1ff0 100644 --- a/src/Logic/ImageProviders/WikimediaImageProvider.ts +++ b/src/Logic/ImageProviders/WikimediaImageProvider.ts @@ -155,9 +155,9 @@ export class WikimediaImageProvider extends ImageProvider { return [this.UrlForImage("File:" + value)] } - public async DownloadAttribution(img: { url: string }): Promise { - const filename = "File:" + WikimediaImageProvider.extractFileName(img.url) - console.log("Downloading attribution for", filename, img.url) + public async DownloadAttribution(img: { id: string }): Promise { + const filename = "File:" + WikimediaImageProvider.extractFileName(img.id) + console.log("Downloading attribution for", filename, img.id) if (filename === "") { return undefined } diff --git a/src/Logic/Web/NearbyImagesSearch.ts b/src/Logic/Web/NearbyImagesSearch.ts index 3bcb1de3a9..89d5f749cc 100644 --- a/src/Logic/Web/NearbyImagesSearch.ts +++ b/src/Logic/Web/NearbyImagesSearch.ts @@ -27,7 +27,7 @@ class CachedFetcher implements ImageFetcher { private readonly _zoomlevel: number private readonly cache: Map> = new Map< number, - Promise + Promise<(P4CPicture & { id: string })[]> >() public readonly name: string @@ -124,8 +124,8 @@ class ImagesInLoadedDataFetcher implements ImageFetcher { this._searchRadius = searchRadius } - async fetchImages(lat: number, lon: number): Promise { - const foundImages: P4CPicture[] = [] + async fetchImages(lat: number, lon: number): Promise<(P4CPicture & { id: string })[]> { + const foundImages: (P4CPicture & { id: string })[] = [] this.indexedFeatures.features.data.forEach((feature) => { const props = feature.properties const images = [] @@ -149,6 +149,7 @@ class ImagesInLoadedDataFetcher implements ImageFetcher { foundImages.push({ pictureUrl: image, thumbUrl: image, + id: image, coordinates: { lng: centerpoint[0], lat: centerpoint[1] }, provider: "OpenStreetMap", details: { @@ -182,9 +183,10 @@ class ImagesFromPanoramaxFetcher implements ImageFetcher { } } - private static convert(imageData: ImageData): P4CPicture { + private static convert(imageData: ImageData): P4CPicture & { id: string } { const [lng, lat] = imageData.geometry.coordinates return { + id: imageData.id, pictureUrl: imageData.assets.sd.href, coordinates: { lng, lat }, @@ -205,7 +207,7 @@ class ImagesFromPanoramaxFetcher implements ImageFetcher { } } - public async fetchImages(lat: number, lon: number): Promise { + public async fetchImages(lat: number, lon: number): Promise<(P4CPicture & { id: string })[]> { const radiusSettings = [ { place_fov_tolerance: 180, @@ -372,7 +374,7 @@ export class CombinedFetcher { start_captured_at: maxage, panoramas: "no", }), - new P4CImageFetcher("mapillary"), + // new P4CImageFetcher("mapillary"), new P4CImageFetcher("wikicommons"), ].map((f) => new CachedFetcher(f)) } diff --git a/src/UI/Image/ImagePreview.svelte b/src/UI/Image/ImagePreview.svelte index 6cc6f75479..e9cdc0029c 100644 --- a/src/UI/Image/ImagePreview.svelte +++ b/src/UI/Image/ImagePreview.svelte @@ -42,7 +42,6 @@ provider = panoramaInfo.properties.provider } console.log(">>> Got:", panoramaInfo, "by", provider.name) -UI: //actuallyDisplayed.set(image.properties.imageMeta) }) if (Array.isArray(nearbyFeatures)) { From a018f154664c45b75be86481e8f5fe201f16eea0 Mon Sep 17 00:00:00 2001 From: Pieter Vander Vennet Date: Thu, 5 Jun 2025 12:34:55 +0200 Subject: [PATCH 11/17] Scripts: fix delete --- scripts/osm2pgsql/createNewDatabase.ts | 2 +- scripts/osm2pgsql/osmPoiDatabase.ts | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/scripts/osm2pgsql/createNewDatabase.ts b/scripts/osm2pgsql/createNewDatabase.ts index 87ee167488..a4afd31cd7 100644 --- a/scripts/osm2pgsql/createNewDatabase.ts +++ b/scripts/osm2pgsql/createNewDatabase.ts @@ -13,7 +13,7 @@ class CreateNewDatabase extends Script { const overwrite = args[1] === "--overwrite" const db = new OsmPoiDatabase("postgresql://user:password@localhost:5444") const knownDatabases = await db.findSuitableDatabases() - if (knownDatabases.indexOf(targetName) > 0) { + if (knownDatabases.indexOf(OsmPoiDatabase.databaseNameFor(targetName)) > 0) { if (overwrite) { await db.deleteDatabase(targetName) } else { diff --git a/scripts/osm2pgsql/osmPoiDatabase.ts b/scripts/osm2pgsql/osmPoiDatabase.ts index 4789f75876..8b55bcac8c 100644 --- a/scripts/osm2pgsql/osmPoiDatabase.ts +++ b/scripts/osm2pgsql/osmPoiDatabase.ts @@ -104,8 +104,12 @@ export class OsmPoiDatabase { return "osm-poi." + latest } + public static databaseNameFor(date: string) { + return `${OsmPoiDatabase._prefix}.${date}` + } + async createNew(date: string) { - const dbname = `${OsmPoiDatabase._prefix}.${date}` + const dbname = OsmPoiDatabase.databaseNameFor(date) console.log("Attempting to create a new database with name", dbname) const metaclient = this.getMetaClient() await metaclient.connect() From 2bbdec510295da003caf7b8d5cc2695e9847cc7c Mon Sep 17 00:00:00 2001 From: Pieter Vander Vennet Date: Thu, 5 Jun 2025 13:58:37 +0200 Subject: [PATCH 12/17] Scripts: attempt to fix android build --- .forgejo/workflows/on_release.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.forgejo/workflows/on_release.yml b/.forgejo/workflows/on_release.yml index 83e4c6631f..5b8b05067e 100644 --- a/.forgejo/workflows/on_release.yml +++ b/.forgejo/workflows/on_release.yml @@ -42,7 +42,7 @@ jobs: run: npm run android:prepare - name: Decode keystore - run: echo "${{ secrets.KEYSTORE_BASE64 }}" | base64 -d > ~/.gradle/release-key.jks + run: echo "${{ secrets.KEYSTORE_BASE64 }}" | base64 -d > ./release-key.jks - name: Grant execute permission to gradlew run: cd android && chmod +x ./gradlew @@ -52,7 +52,7 @@ jobs: cd android export ANDROID_SDK_HOME=/home/runner/.android/sdk/ export PATH=$ANDROID_SDK_HOME/tools:$ANDROID_SDK_HOME/platform-tools:$ANDROID_SDK_HOME/:$ANDROID_SDK_HOME/cmdline-tools/latest/tools/bin:$PATH - export storeFile=my-release-key.jks + export storeFile=./release-key.jks export storePassword=${{ secrets.KEYSTORE_PASSWORD }} export keyAlias=${{ secrets.KEY_ALIAS }} export keyPassword=${{ secrets.KEY_PASSWORD }} From 92ed0628b9886ecf1a7398743e9fe8fa2b4788c9 Mon Sep 17 00:00:00 2001 From: Pieter Vander Vennet Date: Thu, 5 Jun 2025 13:59:14 +0200 Subject: [PATCH 13/17] Scripts: add workflow dispatch --- .forgejo/workflows/on_release.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.forgejo/workflows/on_release.yml b/.forgejo/workflows/on_release.yml index 5b8b05067e..507a18e187 100644 --- a/.forgejo/workflows/on_release.yml +++ b/.forgejo/workflows/on_release.yml @@ -1,4 +1,5 @@ on: + workflow_dispatch: push: tags: - 'v*' From 62e7e345198141e2fcbafcb8a9f990a4543ee252 Mon Sep 17 00:00:00 2001 From: Pieter Vander Vennet Date: Thu, 5 Jun 2025 14:45:51 +0200 Subject: [PATCH 14/17] Scripts: attempt to fix android build --- ...=> Trimm-Dich-Pfad_Grunwalder_Forst_Klimmzuge.jpg} | Bin assets/layers/fitness_station/license_info.json | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) rename assets/layers/fitness_station/{Trimm-Dich-Pfad_Grünwalder_Forst_Klimmzüge.jpg => Trimm-Dich-Pfad_Grunwalder_Forst_Klimmzuge.jpg} (100%) diff --git a/assets/layers/fitness_station/Trimm-Dich-Pfad_Grünwalder_Forst_Klimmzüge.jpg b/assets/layers/fitness_station/Trimm-Dich-Pfad_Grunwalder_Forst_Klimmzuge.jpg similarity index 100% rename from assets/layers/fitness_station/Trimm-Dich-Pfad_Grünwalder_Forst_Klimmzüge.jpg rename to assets/layers/fitness_station/Trimm-Dich-Pfad_Grunwalder_Forst_Klimmzuge.jpg diff --git a/assets/layers/fitness_station/license_info.json b/assets/layers/fitness_station/license_info.json index 89f250c60c..4e44b9d869 100644 --- a/assets/layers/fitness_station/license_info.json +++ b/assets/layers/fitness_station/license_info.json @@ -242,7 +242,7 @@ ] }, { - "path": "Trimm-Dich-Pfad_Grünwalder_Forst_Klimmzüge.jpg", + "path": "Trimm-Dich-Pfad_Grunwalder_Forst_Klimmzuge.jpg", "license": "CC-BY-SA-4.0", "authors": [ "Zeitlupe" @@ -261,4 +261,4 @@ "https://github.com/gravitystorm/openstreetmap-carto/blob/master/symbols/leisure/fitness.svg" ] } -] \ No newline at end of file +] From e13a5a07027004dc7ae7c3795db1e9e879f37fe6 Mon Sep 17 00:00:00 2001 From: Pieter Vander Vennet Date: Thu, 5 Jun 2025 15:10:28 +0200 Subject: [PATCH 15/17] Fix: actually apply namechange in layerfile --- .../Trimm-Dich-Pfad_Grunwalder_Forst_Klimmzuge.jpg.license | 2 ++ assets/layers/fitness_station/fitness_station.json | 2 +- assets/layers/fitness_station/license_info.json | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) create mode 100644 assets/layers/fitness_station/Trimm-Dich-Pfad_Grunwalder_Forst_Klimmzuge.jpg.license diff --git a/assets/layers/fitness_station/Trimm-Dich-Pfad_Grunwalder_Forst_Klimmzuge.jpg.license b/assets/layers/fitness_station/Trimm-Dich-Pfad_Grunwalder_Forst_Klimmzuge.jpg.license new file mode 100644 index 0000000000..9f9bc3b1b2 --- /dev/null +++ b/assets/layers/fitness_station/Trimm-Dich-Pfad_Grunwalder_Forst_Klimmzuge.jpg.license @@ -0,0 +1,2 @@ +SPDX-FileCopyrightText: Zeitlupe +SPDX-License-Identifier: CC-BY-SA-4.0 \ No newline at end of file diff --git a/assets/layers/fitness_station/fitness_station.json b/assets/layers/fitness_station/fitness_station.json index 3d934c2988..be3a3b8a2c 100644 --- a/assets/layers/fitness_station/fitness_station.json +++ b/assets/layers/fitness_station/fitness_station.json @@ -166,7 +166,7 @@ "it": "Questa stazione fitness ha una sbarra orizzontale, abbastanza alta per le trazioni." }, "icon": { - "path": "./assets/layers/fitness_station/Trimm-Dich-Pfad_Grünwalder_Forst_Klimmzüge.jpg", + "path": "./assets/layers/fitness_station/Trimm-Dich-Pfad_Grunwalder_Forst_Klimmzuge.jpg", "class": "large" } }, diff --git a/assets/layers/fitness_station/license_info.json b/assets/layers/fitness_station/license_info.json index 4e44b9d869..3f64204d2a 100644 --- a/assets/layers/fitness_station/license_info.json +++ b/assets/layers/fitness_station/license_info.json @@ -261,4 +261,4 @@ "https://github.com/gravitystorm/openstreetmap-carto/blob/master/symbols/leisure/fitness.svg" ] } -] +] \ No newline at end of file From 3736f8c0b74573d3785df105991787e5db07436a Mon Sep 17 00:00:00 2001 From: Pieter Vander Vennet Date: Thu, 5 Jun 2025 15:42:45 +0200 Subject: [PATCH 16/17] Fix: attempt to get build working --- .forgejo/workflows/on_release.yml | 3 ++- android | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.forgejo/workflows/on_release.yml b/.forgejo/workflows/on_release.yml index 507a18e187..dbc5b7fe47 100644 --- a/.forgejo/workflows/on_release.yml +++ b/.forgejo/workflows/on_release.yml @@ -53,7 +53,8 @@ jobs: cd android export ANDROID_SDK_HOME=/home/runner/.android/sdk/ export PATH=$ANDROID_SDK_HOME/tools:$ANDROID_SDK_HOME/platform-tools:$ANDROID_SDK_HOME/:$ANDROID_SDK_HOME/cmdline-tools/latest/tools/bin:$PATH - export storeFile=./release-key.jks + # Those variables are used in MapComplete/android/app/build.gradle + export storeFile="./release-key.jks" export storePassword=${{ secrets.KEYSTORE_PASSWORD }} export keyAlias=${{ secrets.KEY_ALIAS }} export keyPassword=${{ secrets.KEY_PASSWORD }} diff --git a/android b/android index 921863589c..fc597bf3c9 160000 --- a/android +++ b/android @@ -1 +1 @@ -Subproject commit 921863589c14e1a3002a6be491337de6fe8778dd +Subproject commit fc597bf3c9ebf1280af4e991557d66f5d5838a24 From 0c82fd54385d5f23a3708d428d801d0189c21a2f Mon Sep 17 00:00:00 2001 From: Pieter Vander Vennet Date: Thu, 5 Jun 2025 16:22:50 +0200 Subject: [PATCH 17/17] Fix: attempt to get android build working --- .forgejo/workflows/on_release.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.forgejo/workflows/on_release.yml b/.forgejo/workflows/on_release.yml index dbc5b7fe47..8a6092e4a8 100644 --- a/.forgejo/workflows/on_release.yml +++ b/.forgejo/workflows/on_release.yml @@ -43,7 +43,10 @@ jobs: run: npm run android:prepare - name: Decode keystore - run: echo "${{ secrets.KEYSTORE_BASE64 }}" | base64 -d > ./release-key.jks + run: | + echo "${{ secrets.KEYSTORE_BASE64 }}" | base64 -d > ./android/app/release-key.jks + pwd + echo "Saved release key to ./android/app/release-key.jks" - name: Grant execute permission to gradlew run: cd android && chmod +x ./gradlew