Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions lib/routes/world/world_map.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import 'package:flutter_map/flutter_map.dart';
import 'package:go_router/go_router.dart';
import 'package:latlong2/latlong.dart';
import 'package:matrix/matrix.dart';
import 'package:vector_map_tiles/vector_map_tiles.dart';

import 'package:fluffychat/features/activity_sessions/activity_plan_repo.dart';
import 'package:fluffychat/features/course_plans/courses/course_plan_room_extension.dart';
Expand Down Expand Up @@ -89,6 +90,15 @@ class WorldMapController extends State<WorldMap>
with SingleTickerProviderStateMixin {
final MapController _ownController = MapController();

/// #7077: the OpenFreeMap dark vector style, loaded ONCE. A single Style read
/// fans out to the tilejson, glyphs, and sprite; the dark base layer
/// FutureBuilds on this and falls back to the CartoDB raster until it resolves
/// (or if it errors), so dark mode is never blank. `late final` so it is
/// created on first access only — i.e. only in dark mode.
late final Future<Style> darkMapStyle = StyleReader(
uri: 'https://tiles.openfreemap.org/styles/dark',
).read();

/// The activity pins currently shown — the active context's set (the whole
/// world, or a selected quest's activities). Thin: id, title, point.
List<QuestActivityCard> _pins = [];
Expand Down
47 changes: 36 additions & 11 deletions lib/routes/world/world_map_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:flutter_map_marker_cluster/flutter_map_marker_cluster.dart';
import 'package:latlong2/latlong.dart';
import 'package:vector_map_tiles/vector_map_tiles.dart';

import 'package:fluffychat/config/app_config.dart';
import 'package:fluffychat/config/themes.dart';
Expand Down Expand Up @@ -197,16 +198,39 @@ class WorldMapView extends StatelessWidget {
onPositionChanged: (_, _) => controller.handleMapPositionChanged(),
),
children: [
// Base tiles, switched by app theme: OpenStreetMap (light) / CartoDB
// Dark Matter (dark). Retina (@2x) keeps the dark basemap's small
// labels sharp; CartoDB serves @2x, light (OSM) stays 1x.
TileLayer(
urlTemplate: dark
? 'https://a.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png'
: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
retinaMode: retina,
userAgentPackageName: 'com.talktolearn.chat',
),
// Base map. LIGHT is Phase-1 OSM raster (already legible, zero client
// CPU). DARK is Phase-2 OpenFreeMap VECTOR (#7077): one styled source so
// the label contrast + water are ours, no second request. The vector
// style loads async; until it resolves — and if it ever errors — we fall
// back to the CartoDB raster so dark mode is never blank. layerMode
// defaults to raster (each vector tile is rasterized once and blitted),
// which keeps the per-frame cost off the UI thread on CanvasKit web.
if (dark)
FutureBuilder<Style>(
future: controller.darkMapStyle,
builder: (context, snapshot) {
final style = snapshot.data;
if (style == null) {
return TileLayer(
urlTemplate:
'https://a.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png',
retinaMode: retina,
userAgentPackageName: 'com.talktolearn.chat',
);
}
return VectorTileLayer(
theme: style.theme,
sprites: style.sprites,
tileProviders: style.providers,
maximumZoom: 18,
);
},
)
else
TileLayer(
urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
userAgentPackageName: 'com.talktolearn.chat',
),
// world_v2: activity pins by relevance tier + state. Small dots (the
// long tail) and mid pins (promoted matches) are clustered for
// Google-Maps de-overlap; the 1–3 large featured cards render
Expand Down Expand Up @@ -260,7 +284,8 @@ class WorldMapView extends StatelessWidget {
RichAttributionWidget(
attributions: [
TextSourceAttribution('OpenStreetMap contributors', onTap: () {}),
if (dark) TextSourceAttribution('CARTO', onTap: () {}),
// Dark uses OpenFreeMap vector tiles (OpenMapTiles schema) — #7077.
if (dark) TextSourceAttribution('OpenMapTiles', onTap: () {}),
],
),
],
Expand Down
80 changes: 68 additions & 12 deletions pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -293,10 +293,10 @@ packages:
dependency: "direct main"
description:
name: characters
sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b
sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803
url: "https://pub.dev"
source: hosted
version: "1.4.1"
version: "1.4.0"
charcode:
dependency: transitive
description:
Expand Down Expand Up @@ -546,6 +546,14 @@ packages:
url: "https://github.com/busslina/excel.git"
source: git
version: "4.0.6"
executor_lib:
dependency: transitive
description:
name: executor_lib
sha256: "95ddf2957d9942d9702855b38dd49677f0ee6a8b77d7b16c0e509c7669d17386"
url: "https://pub.dev"
source: hosted
version: "1.1.2"
fake_async:
dependency: transitive
description:
Expand Down Expand Up @@ -1199,6 +1207,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "4.1.2"
idb_shim:
dependency: transitive
description:
name: idb_shim
sha256: "48be1c95f06c4b059d0f5b9888dc5d7384e4a9e4d71824ae2deeb1e1546c6c07"
url: "https://pub.dev"
source: hosted
version: "2.9.2"
image:
dependency: "direct main"
description:
Expand Down Expand Up @@ -1496,18 +1512,18 @@ packages:
dependency: transitive
description:
name: matcher
sha256: dc0b7dc7651697ea4ff3e69ef44b0407ea32c487a39fff6a4004fa585e901861
sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2
url: "https://pub.dev"
source: hosted
version: "0.12.19"
version: "0.12.17"
material_color_utilities:
dependency: transitive
description:
name: material_color_utilities
sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b"
sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
url: "https://pub.dev"
source: hosted
version: "0.13.0"
version: "0.11.1"
material_symbols_icons:
dependency: "direct main"
description:
Expand Down Expand Up @@ -1877,6 +1893,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.1"
protobuf:
dependency: transitive
description:
name: protobuf
sha256: "68645b24e0716782e58948f8467fd42a880f255096a821f9e7d0ec625b00c84d"
url: "https://pub.dev"
source: hosted
version: "3.1.0"
provider:
dependency: "direct main"
description:
Expand Down Expand Up @@ -2117,6 +2141,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.3.2"
sembast:
dependency: transitive
description:
name: sembast
sha256: "139cf71496105de32e7a08a4e3a1ead0f81c4a616ec9703ed07e8f0d10cdd505"
url: "https://pub.dev"
source: hosted
version: "3.8.6"
sentry:
dependency: transitive
description:
Expand Down Expand Up @@ -2438,26 +2470,26 @@ packages:
dependency: transitive
description:
name: test
sha256: "280d6d890011ca966ad08df7e8a4ddfab0fb3aa49f96ed6de56e3521347a9ae7"
sha256: "75906bf273541b676716d1ca7627a17e4c4070a3a16272b7a3dc7da3b9f3f6b7"
url: "https://pub.dev"
source: hosted
version: "1.30.0"
version: "1.26.3"
test_api:
dependency: transitive
description:
name: test_api
sha256: "8161c84903fd860b26bfdefb7963b3f0b68fee7adea0f59ef805ecca346f0c7a"
sha256: ab2726c1a94d3176a45960b6234466ec367179b87dd74f1611adb1f3b5fb9d55
url: "https://pub.dev"
source: hosted
version: "0.7.10"
version: "0.7.7"
test_core:
dependency: transitive
description:
name: test_core
sha256: "0381bd1585d1a924763c308100f2138205252fb90c9d4eeaf28489ee65ccde51"
sha256: "0cc24b5ff94b38d2ae73e1eb43cc302b77964fbf67abad1e296025b78deb53d0"
url: "https://pub.dev"
source: hosted
version: "0.6.16"
version: "0.6.12"
timezone:
dependency: transitive
description:
Expand Down Expand Up @@ -2666,6 +2698,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.1.20"
vector_map_tiles:
dependency: "direct main"
description:
name: vector_map_tiles
sha256: ec9c59c9254f57930f514a523967d5e7082e956878dd9fec942b168b64270c1f
url: "https://pub.dev"
source: hosted
version: "9.0.0-beta.9"
vector_math:
dependency: transitive
description:
Expand All @@ -2674,6 +2714,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.2.0"
vector_tile:
dependency: transitive
description:
name: vector_tile
sha256: "7ae290246e3a8734422672dbe791d3f7b8ab631734489fc6d405f1cc2080e38c"
url: "https://pub.dev"
source: hosted
version: "2.0.1"
vector_tile_renderer:
dependency: transitive
description:
name: vector_tile_renderer
sha256: "982ae5d8f0ab285463a4cd62e711c8f9a36b9b3112b5a471ae8d4f4838f31537"
url: "https://pub.dev"
source: hosted
version: "6.1.0"
video_compress:
dependency: "direct main"
description:
Expand Down
5 changes: 5 additions & 0 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ dependencies:
flutter_localizations:
sdk: flutter
flutter_map: ^8.2.2
# #7077: OpenFreeMap vector tiles for the dark basemap (single request, client-
# side label/water styling). Pinned EXACT (prerelease) — a caret could resolve
# up into 10.x betas that need Flutter's main channel + Impeller (useless on
# CanvasKit web). 9.0.0-beta.9 targets flutter_map ^8.1.1, which our ^8.2.2 meets.
vector_map_tiles: 9.0.0-beta.9
flutter_new_badger: ^1.1.1
flutter_secure_storage: ^9.2.4
flutter_shortcuts_new: ^2.0.0
Expand Down
Loading