load location filters dynamic

This commit is contained in:
otsmr 2025-04-13 17:20:18 +02:00
parent 1bd33b2013
commit f0e7078ce9
6 changed files with 187 additions and 34 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 167 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.4 KiB

View file

@ -187,6 +187,9 @@ PODS:
- shared_preferences_foundation (0.0.1):
- Flutter
- FlutterMacOS
- sqflite_darwin (0.0.4):
- Flutter
- FlutterMacOS
- sqlite3 (3.49.1):
- sqlite3/common (= 3.49.1)
- sqlite3/common (3.49.1)
@ -237,6 +240,7 @@ DEPENDENCIES:
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
- restart_app (from `.symlinks/plugins/restart_app/ios`)
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
- sqflite_darwin (from `.symlinks/plugins/sqflite_darwin/darwin`)
- sqlite3
- sqlite3_flutter_libs (from `.symlinks/plugins/sqlite3_flutter_libs/darwin`)
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
@ -300,6 +304,8 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/restart_app/ios"
shared_preferences_foundation:
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
sqflite_darwin:
:path: ".symlinks/plugins/sqflite_darwin/darwin"
sqlite3_flutter_libs:
:path: ".symlinks/plugins/sqlite3_flutter_libs/darwin"
url_launcher_ios:
@ -341,6 +347,7 @@ SPEC CHECKSUMS:
SDWebImage: f84b0feeb08d2d11e6a9b843cb06d75ebf5b8868
SDWebImageWebPCoder: e38c0a70396191361d60c092933e22c20d5b1380
shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7
sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0
sqlite3: fc1400008a9b3525f5914ed715a5d1af0b8f4983
sqlite3_flutter_libs: f6acaa2172e6bb3e2e70c771661905080e8ebcf2
url_launcher_ios: 694010445543906933d732453a59da0a173ae33d

View file

@ -2,8 +2,12 @@ import 'package:flutter/material.dart';
import 'package:twonly/globals.dart';
import 'package:twonly/src/components/image_editor/layers/filter_layer.dart';
import 'package:twonly/src/components/image_editor/layers/filters/datetime_filter.dart';
import 'package:twonly/src/components/image_editor/layers/filters/image_filter.dart';
import 'package:twonly/src/proto/api/server_to_client.pb.dart';
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:path_provider/path_provider.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'dart:io';
class LocationFilter extends StatefulWidget {
const LocationFilter({super.key});
@ -12,17 +16,8 @@ class LocationFilter extends StatefulWidget {
State<LocationFilter> createState() => _LocationFilterState();
}
Map<String, String> cities = {
"Frankfurt am Main": "germany_frankfurt_am_main.png",
};
Map<String, String> countries = {
"Germany": "germany.png",
};
class _LocationFilterState extends State<LocationFilter> {
String? selectedImage;
String overlayText = "";
String? _imageUrl;
Response_Location? location;
@override
@ -35,34 +30,60 @@ class _LocationFilterState extends State<LocationFilter> {
final res = await apiProvider.getCurrentLocation();
if (res.isSuccess) {
location = res.value.location;
if (cities.containsKey(location!.city)) {
selectedImage = cities[location!.city];
overlayText = location!.city;
} else if (countries.containsKey(location!.county)) {
selectedImage = countries[location!.county];
overlayText = location!.county;
}
_searchForImage();
setState(() {});
}
}
void _searchForImage() async {
if (location == null) return;
List<String> imageIndex = await getStickerIndex();
// Normalize the city and country for search
String normalizedCity = location!.city.toLowerCase().replaceAll(' ', '_');
String normalizedCountry = location!.county.toLowerCase();
// Search for the city first
for (var item in imageIndex) {
if (item.contains('/cities/$normalizedCountry/')) {
// Check if the item matches the normalized city
if (item.endsWith('$normalizedCity.png')) {
if (item.startsWith("/api/")) {
_imageUrl = "https://twonly.eu/$item";
setState(() {});
}
return;
}
}
}
// If city not found, search for the country
if (_imageUrl == null) {
for (var item in imageIndex) {
if (item.contains('/countries/') && item.contains(normalizedCountry)) {
if (item.startsWith("/api/")) {
_imageUrl = "https://twonly.eu/$item";
setState(() {});
}
break;
}
}
}
}
@override
Widget build(BuildContext context) {
if (selectedImage != null) {
return Stack(
children: [
ImageFilter(imagePath: "location/${selectedImage!}"),
Positioned(
bottom: 55,
left: 0,
right: 0,
child: Center(
child: Text(overlayText),
if (_imageUrl != null) {
return FilterSceleton(
child: Positioned(
bottom: 0,
left: 40,
right: 40,
child: Center(
child: CachedNetworkImage(
imageUrl: _imageUrl!,
),
)
],
),
),
);
}
@ -76,7 +97,6 @@ class _LocationFilterState extends State<LocationFilter> {
mainAxisAlignment: MainAxisAlignment.start,
children: [
FilterText(location!.city),
FilterText(location!.region),
FilterText(location!.county),
],
),
@ -88,3 +108,25 @@ class _LocationFilterState extends State<LocationFilter> {
return DateTimeFilter(color: Colors.black);
}
}
Future<List<String>> getStickerIndex() async {
final directory = await getApplicationCacheDirectory();
final indexFile = File('${directory.path}/index.json');
if (await indexFile.exists()) {
final lastModified = await indexFile.lastModified();
final difference = DateTime.now().difference(lastModified);
if (difference.inHours < 24) {
final content = await indexFile.readAsString();
return await json.decode(content).whereType<String>().toList();
}
}
final response =
await http.get(Uri.parse('https://twonly.eu/api/sticker/index.json'));
if (response.statusCode == 200) {
await indexFile.writeAsString(response.body);
return json.decode(response.body).whereType<String>().toList();
} else {
return [];
}
}

View file

@ -137,6 +137,30 @@ packages:
url: "https://pub.dev"
source: hosted
version: "8.9.5"
cached_network_image:
dependency: "direct main"
description:
name: cached_network_image
sha256: "7c1183e361e5c8b0a0f21a28401eecdbde252441106a9816400dd4c2b2424916"
url: "https://pub.dev"
source: hosted
version: "3.4.1"
cached_network_image_platform_interface:
dependency: transitive
description:
name: cached_network_image_platform_interface
sha256: "35814b016e37fbdc91f7ae18c8caf49ba5c88501813f73ce8a07027a395e2829"
url: "https://pub.dev"
source: hosted
version: "4.1.1"
cached_network_image_web:
dependency: transitive
description:
name: cached_network_image_web
sha256: "980842f4e8e2535b8dbd3d5ca0b1f0ba66bf61d14cc3a17a9b4788a3685ba062"
url: "https://pub.dev"
source: hosted
version: "1.3.1"
camera:
dependency: "direct main"
description:
@ -438,6 +462,14 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
flutter_cache_manager:
dependency: transitive
description:
name: flutter_cache_manager
sha256: "400b6592f16a4409a7f2bb929a9a7e38c72cceb8ffb99ee57bbf2cb2cecf8386"
url: "https://pub.dev"
source: hosted
version: "3.4.1"
flutter_image_compress:
dependency: "direct main"
description:
@ -964,6 +996,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.3.1"
octo_image:
dependency: transitive
description:
name: octo_image
sha256: "34faa6639a78c7e3cbe79be6f9f96535867e879748ade7d17c9b1ae7536293bd"
url: "https://pub.dev"
source: hosted
version: "2.1.0"
optional:
dependency: transitive
description:
@ -1228,6 +1268,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.3.2"
rxdart:
dependency: transitive
description:
name: rxdart
sha256: "5c3004a4a8dbb94bd4bf5412a4def4acdaa12e12f269737a5751369e12d1a962"
url: "https://pub.dev"
source: hosted
version: "0.28.0"
screenshot:
dependency: "direct main"
description:
@ -1345,6 +1393,46 @@ packages:
url: "https://pub.dev"
source: hosted
version: "7.0.0"
sqflite:
dependency: transitive
description:
name: sqflite
sha256: e2297b1da52f127bc7a3da11439985d9b536f75070f3325e62ada69a5c585d03
url: "https://pub.dev"
source: hosted
version: "2.4.2"
sqflite_android:
dependency: transitive
description:
name: sqflite_android
sha256: "2b3070c5fa881839f8b402ee4a39c1b4d561704d4ebbbcfb808a119bc2a1701b"
url: "https://pub.dev"
source: hosted
version: "2.4.1"
sqflite_common:
dependency: transitive
description:
name: sqflite_common
sha256: "84731e8bfd8303a3389903e01fb2141b6e59b5973cacbb0929021df08dddbe8b"
url: "https://pub.dev"
source: hosted
version: "2.5.5"
sqflite_darwin:
dependency: transitive
description:
name: sqflite_darwin
sha256: "279832e5cde3fe99e8571879498c9211f3ca6391b0d818df4e17d9fff5c6ccb3"
url: "https://pub.dev"
source: hosted
version: "2.4.2"
sqflite_platform_interface:
dependency: transitive
description:
name: sqflite_platform_interface
sha256: "8dd4515c7bdcae0a785b0062859336de775e8c65db81ae33dd5445f35be61920"
url: "https://pub.dev"
source: hosted
version: "2.4.0"
sqlite3:
dependency: transitive
description:
@ -1401,6 +1489,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.4.1"
synchronized:
dependency: transitive
description:
name: synchronized
sha256: "0669c70faae6270521ee4f05bffd2919892d42d1276e6c495be80174b6bc0ef6"
url: "https://pub.dev"
source: hosted
version: "3.3.1"
term_glyph:
dependency: transitive
description:
@ -1505,6 +1601,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.1.4"
uuid:
dependency: transitive
description:
name: uuid
sha256: a5be9ef6618a7ac1e964353ef476418026db906c4facdedaa299b7a2e71690ff
url: "https://pub.dev"
source: hosted
version: "4.5.1"
vector_graphics:
dependency: transitive
description:

View file

@ -62,6 +62,7 @@ dependencies:
flutter_volume_controller: ^1.3.3
fixnum: ^1.1.1
mutex: ^3.1.0
cached_network_image: ^3.4.1
# avatar_maker
# avatar_maker:
# path: ./dependencies/avatar_maker/
@ -96,6 +97,5 @@ flutter:
- assets/animated_icons/
- assets/animations/
- assets/filters/
- assets/filters/location/
- assets/filters/random/