Skip to content

Commit

Permalink
chore: Did some refactoring with jovial_svg.
Browse files Browse the repository at this point in the history
  • Loading branch information
Skyost committed Oct 23, 2024
1 parent be0cf0c commit e230f94
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 69 deletions.
26 changes: 3 additions & 23 deletions lib/model/totp/image_cache.dart
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:http/http.dart' as http;
import 'package:jovial_misc/io_utils.dart';
import 'package:jovial_svg/src/compact_noui.dart';
import 'package:jovial_svg/src/svg_parser.dart';
import 'package:open_authenticator/model/settings/cache_totp_pictures.dart';
import 'package:open_authenticator/model/totp/decrypted.dart';
import 'package:open_authenticator/model/totp/repository.dart';
import 'package:open_authenticator/model/totp/totp.dart';
import 'package:open_authenticator/utils/image_type.dart';
import 'package:open_authenticator/utils/jovial_svg.dart';
import 'package:open_authenticator/utils/utils.dart';
import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';
Expand Down Expand Up @@ -46,7 +43,7 @@ class TotpImageCacheManager extends AutoDisposeAsyncNotifier<Map<String, CacheOb
CacheObject newCacheObject = entry.value.copyWith(legacy: false);
if (entry.value.imageType == ImageType.svg) {
File? cachedImage = (await cached.getCachedImage(entry.key, entry.value.url))?.$1;
if (cachedImage != null && cachedImage.existsSync() && (await _svgToSi(cachedImage.readAsStringSync(), cachedImage))) {
if (cachedImage != null && cachedImage.existsSync() && (await JovialSvgUtils.svgToSi(cachedImage.readAsStringSync(), cachedImage))) {
newCacheObject = entry.value.copyWith(imageType: ImageType.si);
}
}
Expand Down Expand Up @@ -87,7 +84,7 @@ class TotpImageCacheManager extends AutoDisposeAsyncNotifier<Map<String, CacheOb
ImageType imageType;
if (imageUrl.endsWith('.svg')) {
imageType = ImageType.svg;
if (await _svgToSi(response.body, file)) {
if (await JovialSvgUtils.svgToSi(response.body, file)) {
imageType = ImageType.si;
}
} else {
Expand All @@ -107,23 +104,6 @@ class TotpImageCacheManager extends AutoDisposeAsyncNotifier<Map<String, CacheOb
}
}

/// Compiles a SVG string into an SI file.
Future<bool> _svgToSi(String svg, File destinationFile) async {
IOSink ioSink = destinationFile.openWrite();
try {
DataOutputSink outputSink = DataOutputSink(ioSink, Endian.big);
SICompactBuilderNoUI siCompactBuilder = SICompactBuilderNoUI(bigFloats: false, warn: (_) {});
StringSvgParser(svg, [], siCompactBuilder, warn: (_) {}).parse();
siCompactBuilder.si.writeToFile(outputSink);
return true;
} catch (ex, stacktrace) {
handleException(ex, stacktrace);
} finally {
await ioSink.close();
}
return false;
}

/// Deletes the cached image, if possible.
Future<void> deleteCachedImage(String uuid) async {
Map<String, CacheObject> cached = Map.from(await future);
Expand Down
81 changes: 81 additions & 0 deletions lib/utils/jovial_svg.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import 'dart:io';
import 'dart:typed_data';

import 'package:flutter/services.dart';
import 'package:jovial_misc/io_utils.dart';
import 'package:jovial_svg/jovial_svg.dart';
import 'package:jovial_svg/src/compact.dart';
import 'package:jovial_svg/src/compact_noui.dart';
import 'package:jovial_svg/src/svg_parser.dart';
import 'package:open_authenticator/utils/utils.dart';

/// Contains some useful methods to use with `jovial_svg`.
class JovialSvgUtils {
/// Compiles a SVG string into an SI file.
static Future<bool> svgToSi(String svg, File destinationFile) async {
IOSink ioSink = destinationFile.openWrite();
try {
DataOutputSink outputSink = DataOutputSink(ioSink, Endian.big);
SICompactBuilderNoUI siCompactBuilder = SICompactBuilderNoUI(bigFloats: false, warn: (_) {});
StringSvgParser(svg, [], siCompactBuilder, warn: (_) {}).parse();
siCompactBuilder.si.writeToFile(outputSink);
return true;
} catch (ex, stacktrace) {
handleException(ex, stacktrace);
} finally {
await ioSink.close();
}
return false;
}

/// Loads an SI graphic from a file or from an asset.
static ScalableImageSource siFromFileOrAsset(String source) {
File file = File(source);
return file.existsSync()
? SIFileSource(file, null)
: ScalableImageSource.fromSI(
rootBundle,
source,
);
}
}

/// Allows to load a SI image from a file.
class SIFileSource extends ScalableImageSource {
/// File file.
final File file;

/// The current color.
final Color? currentColor;

/// Creates a new SI file source instance.
SIFileSource(this.file, this.currentColor);

@override
Future<ScalableImage> get si => createSI();

@override
Future<ScalableImage> createSI({bool compact = false}) async {
ScalableImageCompact scalableImageCompact = ScalableImageCompact.fromBytes(file.readAsBytesSync(), currentColor: currentColor);
if (compact) {
return scalableImageCompact;
} else {
return scalableImageCompact.toDag();
}
}

@override
bool operator ==(final Object other) {
if (other is SIFileSource) {
return file == other.file && currentColor == other.currentColor;
} else {
return false;
}
}

@override
int get hashCode => 0xf67cd716 ^ Object.hash(file, currentColor);

@override
String toString() => '__SIFileSource($file $currentColor)';
}
48 changes: 2 additions & 46 deletions lib/widgets/sized_scalable_image.dart
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:jovial_svg/jovial_svg.dart';
import 'package:jovial_svg/src/compact.dart';
import 'package:open_authenticator/utils/jovial_svg.dart';

/// A sized scalable image widget.
class SizedScalableImageWidget extends StatelessWidget {
Expand Down Expand Up @@ -42,14 +39,8 @@ class SizedScalableImageWidget extends StatelessWidget {

@override
Widget build(BuildContext context) {
File file = File(asset);
Widget child = ScalableImageWidget.fromSISource(
si: file.existsSync()
? _SIFileSource(file, null)
: ScalableImageSource.fromSI(
rootBundle,
asset,
),
si: JovialSvgUtils.siFromFileOrAsset(asset),
fit: fit,
alignment: alignment,
);
Expand Down Expand Up @@ -80,38 +71,3 @@ class SizedScalableImageWidget extends StatelessWidget {
return child;
}
}

class _SIFileSource extends ScalableImageSource {
final File file;
final Color? currentColor;

_SIFileSource(this.file, this.currentColor);

@override
Future<ScalableImage> get si => createSI();

@override
Future<ScalableImage> createSI({bool compact = false}) async {
ScalableImageCompact scalableImageCompact = ScalableImageCompact.fromBytes(file.readAsBytesSync(), currentColor: currentColor);
if (compact) {
return scalableImageCompact;
} else {
return scalableImageCompact.toDag();
}
}

@override
bool operator ==(final Object other) {
if (other is _SIFileSource) {
return file == other.file && currentColor == other.currentColor;
} else {
return false;
}
}

@override
int get hashCode => 0xf67cd716 ^ Object.hash(file, currentColor);

@override
String toString() => '__SIFileSource($file $currentColor)';
}

0 comments on commit e230f94

Please sign in to comment.