install theme from zip archive functionality

This commit is contained in:
julian 2023-05-09 17:18:13 -06:00
parent 848b1c3bbd
commit 604e4cfde7
3 changed files with 66 additions and 3 deletions

View file

@ -1,9 +1,14 @@
import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
import 'package:archive/archive_io.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:isar/isar.dart';
import 'package:stackwallet/db/isar/main_db.dart';
import 'package:stackwallet/models/isar/stack_theme.dart';
import 'package:stackwallet/utilities/logger.dart';
import 'package:stackwallet/utilities/stack_file_system.dart';
final pThemeService = Provider<ThemeService>((ref) {
return ThemeService.instance;
@ -20,11 +25,68 @@ class ThemeService {
void init(MainDB db) => _db ??= db;
Future<void> install({required ByteData themeArchive}) async {
// todo unzip, install, and create theme object and add to db
final themesDir = await StackFileSystem.applicationThemesDirectory();
final byteStream = InputStream(themeArchive);
final archive = ZipDecoder().decodeBuffer(byteStream);
final themeJsonFiles = archive.files.where((e) => e.name == "theme.json");
if (themeJsonFiles.length != 1) {
throw Exception("Invalid theme archive: Missing theme.json");
}
final OutputStream os = OutputStream();
themeJsonFiles.first.decompress(os);
final String jsonString = utf8.decode(os.getBytes());
final json = jsonDecode(jsonString) as Map;
final theme = StackTheme.fromJson(
json: Map<String, dynamic>.from(json),
applicationThemesDirectoryPath: themesDir.path,
);
final String assetsPath = "${themesDir.path}/${theme.themeId}";
for (final file in archive.files) {
if (file.isFile) {
// TODO more sanitation?
if (file.name.contains("..")) {
Logging.instance.log(
"Bad theme asset file path: ${file.name}",
level: LogLevel.Error,
);
} else {
final os = OutputFileStream("$assetsPath/${file.name}");
file.writeContent(os);
await os.close();
}
}
}
await db.isar.writeTxn(() async {
await db.isar.stackThemes.put(theme);
});
}
Future<void> remove({required String themeId}) async {
// todo delete local files and remove from db
final themesDir = await StackFileSystem.applicationThemesDirectory();
final isarId = await db.isar.stackThemes
.where()
.themeIdEqualTo(themeId)
.idProperty()
.findFirst();
if (isarId != null) {
await db.isar.writeTxn(() async {
await db.isar.stackThemes.delete(isarId);
});
await Directory("${themesDir.path}/$themeId").delete(recursive: true);
} else {
Logging.instance.log(
"Failed to delete theme $themeId",
level: LogLevel.Warning,
);
}
}
Future<List<Map<String, dynamic>>> fetchThemeList() async {

View file

@ -42,7 +42,7 @@ packages:
source: hosted
version: "4.2.0"
archive:
dependency: transitive
dependency: "direct main"
description:
name: archive
sha256: "80e5141fafcb3361653ce308776cfd7d45e6e9fbb429e14eec571382c0c5fecb"

View file

@ -151,6 +151,7 @@ dependencies:
dart_bs58check: ^3.0.2
hex: ^0.2.0
rational: ^2.2.2
archive: ^3.3.2
dev_dependencies:
flutter_test: