Skip to content
Merged
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
2 changes: 1 addition & 1 deletion android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ android {
applicationId 'com.exptech.dpip'
minSdkVersion 26
targetSdkVersion 36
versionCode 300104018
versionCode 300104019
versionName flutterVersionName
multiDexEnabled true
resConfigs "en", "ko", "zh-rTW", "ja", "zh-rCN"
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
49 changes: 18 additions & 31 deletions ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,6 @@ PODS:
- Flutter
- fluttertoast (0.0.2):
- Flutter
- gal (1.0.0):
- Flutter
- FlutterMacOS
- geolocator_apple (1.2.0):
- Flutter
- FlutterMacOS
Expand Down Expand Up @@ -165,8 +162,6 @@ PODS:
- FlutterMacOS
- url_launcher_ios (0.0.1):
- Flutter
- zstandard_ios (0.0.1):
- Flutter

DEPENDENCIES:
- awesome_notifications (from `.symlinks/plugins/awesome_notifications/ios`)
Expand All @@ -179,7 +174,6 @@ DEPENDENCIES:
- flutter_compass (from `.symlinks/plugins/flutter_compass/ios`)
- flutter_icmp_ping (from `.symlinks/plugins/flutter_icmp_ping/ios`)
- fluttertoast (from `.symlinks/plugins/fluttertoast/ios`)
- gal (from `.symlinks/plugins/gal/darwin`)
- geolocator_apple (from `.symlinks/plugins/geolocator_apple/darwin`)
- in_app_purchase_storekit (from `.symlinks/plugins/in_app_purchase_storekit/darwin`)
- maplibre_gl (from `.symlinks/plugins/maplibre_gl/ios`)
Expand All @@ -190,7 +184,6 @@ DEPENDENCIES:
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
- sqflite_darwin (from `.symlinks/plugins/sqflite_darwin/darwin`)
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
- zstandard_ios (from `.symlinks/plugins/zstandard_ios/ios`)

SPEC REPOS:
trunk:
Expand Down Expand Up @@ -233,8 +226,6 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/flutter_icmp_ping/ios"
fluttertoast:
:path: ".symlinks/plugins/fluttertoast/ios"
gal:
:path: ".symlinks/plugins/gal/darwin"
geolocator_apple:
:path: ".symlinks/plugins/geolocator_apple/darwin"
in_app_purchase_storekit:
Expand All @@ -255,17 +246,15 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/sqflite_darwin/darwin"
url_launcher_ios:
:path: ".symlinks/plugins/url_launcher_ios/ios"
zstandard_ios:
:path: ".symlinks/plugins/zstandard_ios/ios"

SPEC CHECKSUMS:
awesome_notifications: 0f432b28098d193920b11a44cfa9d2d9313a3888
awesome_notifications_fcm: ad14f584c81e2488ae4310ab96331327dcbb5368
device_info_plus: 21fcca2080fbcd348be798aa36c3e5ed849eefbe
awesome_notifications: dd5518ff1c80be03d4f1c40f04da9d9cc2a37af5
awesome_notifications_fcm: 707931990883faf918db11438bdddded93b2b3a6
device_info_plus: bf2e3232933866d73fe290f2942f2156cdd10342
Firebase: d99ac19b909cd2c548339c2241ecd0d1599ab02e
firebase_core: 995454a784ff288be5689b796deb9e9fa3601818
firebase_crashlytics: 30dcd6dfd2fe895c0848af46722a4227346c19aa
firebase_messaging: f4a41dd102ac18b840eba3f39d67e77922d3f707
firebase_core: 99a37263b3c27536063a7b601d9e2a49400a433c
firebase_messaging: bf6697c61f31c7cc0f654131212ff04c0115c2c7
FirebaseCore: efb3893e5b94f32b86e331e3bd6dadf18b66568e
FirebaseCoreExtension: edbd30474b5ccf04e5f001470bdf6ea616af2435
FirebaseCoreInternal: 9afa45b1159304c963da48addb78275ef701c6b4
Expand All @@ -275,29 +264,27 @@ SPEC CHECKSUMS:
FirebaseRemoteConfigInterop: 1c6135e8a094cc6368949f5faeeca7ee8948b8aa
FirebaseSessions: b9a92c1c51bbb81e78fc3142cda6d925d700f8e7
Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
flutter_compass: b236ab69b61545cce89fd58527f401a7587d5cc1
flutter_icmp_ping: 47c1df3440c18ddd39fc457e607bb3b42d4a339f
fluttertoast: 2c67e14dce98bbdb200df9e1acf610d7a6264ea1
gal: baecd024ebfd13c441269ca7404792a7152fde89
geolocator_apple: ab36aa0e8b7d7a2d7639b3b4e48308394e8cef5e
flutter_compass: cbbd285cea1584c7ac9c4e0c3e1f17cbea55e855
flutter_icmp_ping: 2b159955eee0c487c766ad83fec224ae35e7c935
fluttertoast: 21eecd6935e7064cc1fcb733a4c5a428f3f24f0f
geolocator_apple: 66b711889fd333205763b83c9dcf0a57a28c7afd
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1
in_app_purchase_storekit: 22cca7d08eebca9babdf4d07d0baccb73325d3c8
in_app_purchase_storekit: 2342c0a5da86593124d08dd13d920f39a52b273a
IosAwnCore: 653786a911089012092ce831f2945cd339855a89
IosAwnFcmCore: 1bdb9054b2e00187d00f1ffcfbb1855949a7b82f
MapLibre: 7f24faba45439f80ccb0f83393c29fa32cb81952
maplibre_gl: d83126f1b19adee5e1071c453b421efd5fc99883
maplibre_gl: 5144d1208ed5ee49dfb2023670180f9af5517cce
nanopb: fad817b59e0457d11a5dfbde799381cd727c1275
package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499
path_provider_foundation: bb55f6dbba17d0dccd6737fe6f7f34fbd0376880
permission_handler_apple: 4ed2196e43d0651e8ff7ca3483a069d469701f2d
package_info_plus: c0502532a26c7662a62a356cebe2692ec5fe4ec4
path_provider_foundation: 0b743cbb62d8e47eab856f09262bb8c1ddcfe6ba
permission_handler_apple: 9878588469a2b0d0fc1e048d9f43605f92e6cec2
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
PromisesSwift: 9d77319bbe72ebf6d872900551f7eeba9bce2851
share_plus: 50da8cb520a8f0f65671c6c6a99b3617ed10a58a
shared_preferences_foundation: 7036424c3d8ec98dfe75ff1667cb0cd531ec82bb
sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0
url_launcher_ios: 7a95fa5b60cc718a708b8f2966718e93db0cef1b
zstandard_ios: 09cab18e0ee494020cc24d82a95c5bf4252d240c
share_plus: 8b6f8b3447e494cca5317c8c3073de39b3600d1f
shared_preferences_foundation: 5086985c1d43c5ba4d5e69a4e8083a389e2909e6
sqflite_darwin: 5a7236e3b501866c1c9befc6771dfd73ffb8702d
url_launcher_ios: bb13df5870e8c4234ca12609d04010a21be43dfa

PODFILE CHECKSUM: 3d88bce62bfe048ac33ca00d3fb1bc02caeda4d3

Expand Down
26 changes: 26 additions & 0 deletions ios/Runner/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import CoreLocation
import Flutter
import UIKit
import Intents
import Photos
import UserNotifications

@UIApplicationMain
Expand Down Expand Up @@ -116,6 +117,31 @@ class AppDelegate: FlutterAppDelegate, CLLocationManagerDelegate {
result(FlutterMethodNotImplemented)
}
}

let imageSaverChannel = FlutterMethodChannel(
name: "image_saver",
binaryMessenger: controller.binaryMessenger
)

imageSaverChannel.setMethodCallHandler { call, result in
if call.method == "saveImage",
let args = call.arguments as? [String: Any],
let path = args["path"] as? String {

if let image = UIImage(contentsOfFile: path) {
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil)
result(nil)
} else {
result(FlutterError(
code: "INVALID_IMAGE",
message: "Cannot load image from path",
details: nil
))
}
} else {
result(FlutterMethodNotImplemented)
}
}
}

private func setupLocationManager() {
Expand Down
2 changes: 0 additions & 2 deletions ios/Runner/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,6 @@
<string>DPIP 將利用你的位置資訊,用以自動設定所在地並在地震發生時能較準確地預估所在地的最大震度。</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>用於儲存地震報告圖片。</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>用於儲存地震報告圖片至您的相簿。</string>
<key>NSUserActivityTypes</key>
<array>
<string>OpenMonitorIntentIntent</string>
Expand Down
12 changes: 2 additions & 10 deletions lib/api/exptech.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,14 @@ import 'package:dpip/models/settings/notify.dart';
import 'package:dpip/utils/extensions/response.dart';
import 'package:dpip/utils/extensions/string.dart';
import 'package:dpip/utils/log.dart';
import 'package:es_compression/zstd.dart';
import 'package:http/http.dart' as http;
import 'package:http/io_client.dart';
import 'package:maplibre_gl/maplibre_gl.dart';
import 'package:option_result/result.dart';
import 'package:zstandard/zstandard.dart';

class _GzipClient extends http.BaseClient {
final http.Client _inner;
final Zstandard _zstd = Zstandard();

_GzipClient(this._inner);

Expand All @@ -49,14 +48,7 @@ class _GzipClient extends http.BaseClient {
final compressedBody = await response.stream.toBytes();

try {
final decompressedBody = await _zstd.decompress(compressedBody);

if (decompressedBody == null) {
throw HttpException(
'Failed to decompress zstd response',
uri: request.url,
);
}
final decompressedBody = zstd.decode(compressedBody);

final headers = Map<String, String>.from(response.headers);
headers.remove('content-encoding');
Expand Down
4 changes: 2 additions & 2 deletions lib/core/fcm.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ import 'package:dpip/core/preference.dart';
import 'package:dpip/main.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/foundation.dart';

Future<void> fcmInit() async {
await Firebase.initializeApp();

if (Platform.isAndroid) {
await AwesomeNotificationsFcm().initialize(
onFcmTokenHandle: onTokenHandle,
Expand All @@ -18,7 +18,7 @@ Future<void> fcmInit() async {
licenseKeys: [
'2024-08-26==N0LtVWu49ox9yV8eaDrh8rGyji/iKzLaB6anluLFIPESM/rUtf0OTUDyExMB+hp8YqnfA9UMcwvT5i5lTcsB73WKbh2+cYbYwtSZoxjuSUUbNxzhnlH2uiD7CNYvtniORC69TStgEfXnYZ1dEfWe5p6Nwi4wDS7vTfyTOH2NqCW+5293ypcu6+7se2PxLGOF1s8YKbM3HU8nYk8juChbFNoxX/Y0pHOH+MvXi070o1+3SPL98BS9bPQQ0e9a9MgYpxRqthP/mT1Yx2AX4+d+Qb6NNiz8ub+rl1HhZc7vmy5bntJSwcculDhXG3YOP3uXeYYyc2L+NKqkHPYpflblOg==',
],
debug: true,
debug: kDebugMode,
);
await AwesomeNotificationsFcm().requestFirebaseAppToken();
} else if (Platform.isIOS) {
Expand Down
9 changes: 2 additions & 7 deletions lib/global.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ import 'package:dpip/api/exptech.dart';
import 'package:dpip/api/model/location/location.dart';
import 'package:dpip/utils/extensions/asset_bundle.dart';
import 'package:dpip/utils/log.dart';
import 'package:es_compression/zstd.dart';
import 'package:flutter/services.dart';
import 'package:geojson_vi/geojson_vi.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:zstandard/zstandard.dart';

typedef TimeTable = Map<String, List<({double P, double S, double R})>>;

Expand All @@ -34,12 +34,7 @@ class Global {
late List<int> decompressed;

if (assetPath.endsWith('.zst')) {
final zstd = Zstandard();
final result = await zstd.decompress(bytes);
if (result == null) {
throw Exception('zstd decompress failed');
}
decompressed = result;
decompressed = zstd.decode(bytes);
} else if (assetPath.endsWith('.gz')) {
decompressed = GZipCodec().decode(bytes);
} else {
Expand Down
1 change: 0 additions & 1 deletion lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,6 @@ void main() async {
}

final overallEndTime = DateTime.now();
talker.log('--- 冷啟動偵測結束 ---');
talker.log(
'🚨 總初始化耗時 (runApp 前): ${overallEndTime.difference(overallStartTime).inMilliseconds}ms',
);
Expand Down
25 changes: 13 additions & 12 deletions lib/route/image_viewer/image_viewer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import 'package:dpip/core/i18n.dart';
import 'package:dpip/utils/extensions/build_context.dart';
import 'package:dpip/utils/toast.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:gal/gal.dart';
import 'package:http/http.dart';
import 'package:material_symbols_icons/symbols.dart';
Expand All @@ -28,6 +29,16 @@ class ImageViewerRoute extends StatefulWidget {
State<ImageViewerRoute> createState() => _ImageViewerRouteState();
}

class ImageSaver {
static const _channel = MethodChannel('image_saver');

static Future<void> saveToPhotos(String path) async {
await _channel.invokeMethod('saveImage', {
'path': path,
});
}
}

class _ImageViewerRouteState extends State<ImageViewerRoute> {
final TransformationController _controller = TransformationController();
bool isDownloading = false;
Expand Down Expand Up @@ -92,26 +103,17 @@ class _ImageViewerRouteState extends State<ImageViewerRoute> {

final res = await get(Uri.parse(widget.imageUrl));

// 保存图片到临时目录
final tempDir = await getTemporaryDirectory();
final tempFile = File('${tempDir.path}/${widget.imageName}');
await tempFile.writeAsBytes(res.bodyBytes);

try {
// 保存到相册
if (Platform.isAndroid) {
await Gal.putImage(tempFile.path, album: 'DPIP');
} else {
await Permission.photosAddOnly.request();
try {
await Gal.putImage(tempFile.path);
} catch (_) {
final upgrade = await Permission.photos.request();
if (upgrade.isGranted) {
await Gal.putImage(tempFile.path, album: 'DPIP');
}
}
await ImageSaver.saveToPhotos(tempFile.path);
}
if (!mounted) return;
showToast(
context,
ToastWidget.text(
Expand All @@ -120,7 +122,6 @@ class _ImageViewerRouteState extends State<ImageViewerRoute> {
),
);
} finally {
// 清理临时文件
if (await tempFile.exists()) {
await tempFile.delete();
}
Expand Down
2 changes: 0 additions & 2 deletions macos/Flutter/GeneratedPluginRegistrant.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import share_plus
import shared_preferences_foundation
import sqflite_darwin
import url_launcher_macos
import zstandard_macos

func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
AwesomeNotificationsPlugin.register(with: registry.registrar(forPlugin: "AwesomeNotificationsPlugin"))
Expand All @@ -38,5 +37,4 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
ZstandardMacosPlugin.register(with: registry.registrar(forPlugin: "ZstandardMacosPlugin"))
}
Loading
Loading