Skip to content

Commit

Permalink
Merge branch '413-smartphone-as-a-container' of https://github.com/pr…
Browse files Browse the repository at this point in the history
…ivacyidea/pi-authenticator into 413-smartphone-as-a-container
  • Loading branch information
frankmer committed Nov 29, 2024
2 parents 68e7db6 + d60e4b9 commit c02aa4f
Show file tree
Hide file tree
Showing 15 changed files with 133 additions and 109 deletions.
6 changes: 3 additions & 3 deletions lib/mains/main_customizer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -82,13 +82,13 @@ class CustomizationAuthenticator extends ConsumerWidget {
FeedbackView.routeName: (context) => const FeedbackView(),
ImportTokensView.routeName: (context) => const ImportTokensView(),
LicenseView.routeName: (context) => LicenseView(
appImage: applicationCustomizer.licensesViewImage.getWidget,
appImage: applicationCustomizer.licensesViewImage?.getWidget ?? applicationCustomizer.splashScreenImage.getWidget,
appName: applicationCustomizer.appName,
websiteLink: applicationCustomizer.websiteLink,
),
MainView.routeName: (context) => MainView(
appIcon: applicationCustomizer.appbarIcon.getWidget,
appImage: applicationCustomizer.splashScreenImage.getWidget,
appbarIcon: applicationCustomizer.appbarIcon.getWidget,
backgroundImage: applicationCustomizer.backgroundImage?.getWidget,
appName: applicationCustomizer.appName,
disablePatchNotes: applicationCustomizer.disabledFeatures.contains(AppFeature.patchNotes),
),
Expand Down
6 changes: 3 additions & 3 deletions lib/mains/main_netknights.dart
Original file line number Diff line number Diff line change
Expand Up @@ -104,13 +104,13 @@ class PrivacyIDEAAuthenticator extends ConsumerWidget {
FeedbackView.routeName: (context) => const FeedbackView(),
ImportTokensView.routeName: (context) => const ImportTokensView(),
LicenseView.routeName: (context) => LicenseView(
appImage: _customization.licensesViewImage.getWidget,
appImage: _customization.licensesViewImage?.getWidget ?? _customization.splashScreenImage.getWidget,
appName: _customization.appName,
websiteLink: _customization.websiteLink,
),
MainView.routeName: (context) => MainView(
appIcon: _customization.appbarIcon.getWidget,
appImage: _customization.splashScreenImage.getWidget,
appbarIcon: _customization.appbarIcon.getWidget,
backgroundImage: _customization.backgroundImage?.getWidget,
appName: _customization.appName,
disablePatchNotes: _customization.disabledFeatures.contains(AppFeature.patchNotes),
),
Expand Down
2 changes: 1 addition & 1 deletion lib/model/enums/image_file_type.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
*/

// Do not rename or remove values, they are used for serialization. Only add new values.
enum ImageFileType {
enum ImageFormat {
svg,
svgz,
png,
Expand Down
75 changes: 39 additions & 36 deletions lib/model/extensions/enums/image_file_type_extension.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,86 +25,89 @@ import 'package:image_picker/image_picker.dart';

import '../../enums/image_file_type.dart';

extension ImageFileTypeX on ImageFileType {
static ImageFileType fromExtensionString(String ex) => switch (ex) {
'svg' => ImageFileType.svg,
'svgz' => ImageFileType.svgz,
'png' => ImageFileType.png,
'jpg' => ImageFileType.jpg,
'jpeg' => ImageFileType.jpeg,
'gif' => ImageFileType.gif,
'bmp' => ImageFileType.bmp,
'webp' => ImageFileType.webp,
extension ImageFileTypeX on ImageFormat {
static ImageFormat fromExtensionString(String ex) => switch (ex) {
'svg' => ImageFormat.svg,
'svgz' => ImageFormat.svgz,
'png' => ImageFormat.png,
'jpg' => ImageFormat.jpg,
'jpeg' => ImageFormat.jpeg,
'gif' => ImageFormat.gif,
'bmp' => ImageFormat.bmp,
'webp' => ImageFormat.webp,
_ => throw Exception('Unknown extension: $ex'),
};

Widget buildImageWidget(Uint8List imageData) => switch (this) {
ImageFileType.svg => SvgPicture.memory(
ImageFormat.svg => SvgPicture.memory(
imageData,
colorFilter: ColorFilter.mode(
Colors.transparent,
BlendMode.srcOver,
),
),
ImageFileType.svgz => SvgPicture.memory(
ImageFormat.svgz => SvgPicture.memory(
imageData,
colorFilter: ColorFilter.mode(
Colors.transparent,
BlendMode.srcOver,
),
),
ImageFileType.png => Image.memory(
ImageFormat.png => Image.memory(
imageData,
colorBlendMode: BlendMode.srcOver,
),
ImageFileType.jpg => Image.memory(
ImageFormat.jpg => Image.memory(
imageData,
colorBlendMode: BlendMode.srcOver,
),
ImageFileType.jpeg => Image.memory(
ImageFormat.jpeg => Image.memory(
imageData,
colorBlendMode: BlendMode.srcOver,
),
ImageFileType.gif => Image.memory(
ImageFormat.gif => Image.memory(
imageData,
colorBlendMode: BlendMode.srcOver,
),
ImageFileType.bmp => Image.memory(
ImageFormat.bmp => Image.memory(
imageData,
colorBlendMode: BlendMode.srcOver,
),
ImageFileType.webp => Image.memory(
ImageFormat.webp => Image.memory(
imageData,
colorBlendMode: BlendMode.srcOver,
),
};

String get extension => toString().split('.').last;

String get typeName => switch (this) {
ImageFileType.svg => 'Scalable Vector Graphic',
ImageFileType.svgz => 'Scalable Vector Graphic (compressed)',
ImageFileType.png => 'PNG',
ImageFileType.jpg => 'JPEG',
ImageFileType.jpeg => 'JPEG',
ImageFileType.gif => 'GIF',
ImageFileType.bmp => 'Bitmap',
ImageFileType.webp => 'WebP',
String get name => switch (this) {
ImageFormat.svg => 'Scalable Vector Graphic',
ImageFormat.svgz => 'Scalable Vector Graphic (compressed)',
ImageFormat.png => 'PNG',
ImageFormat.jpg => 'JPEG',
ImageFormat.jpeg => 'JPEG',
ImageFormat.gif => 'GIF',
ImageFormat.bmp => 'Bitmap',
ImageFormat.webp => 'WebP',
};

String get mimeType => switch (this) {
ImageFileType.svg => 'image/svg+xml',
ImageFileType.svgz => 'image/svg+xml',
ImageFileType.png => 'image/png',
ImageFileType.jpg => 'image/jpeg',
ImageFileType.jpeg => 'image/jpeg',
ImageFileType.gif => 'image/gif',
ImageFileType.bmp => 'image/bmp',
ImageFileType.webp => 'image/webp',
ImageFormat.svg => 'image/svg+xml',
ImageFormat.svgz => 'image/svg+xml',
ImageFormat.png => 'image/png',
ImageFormat.jpg => 'image/jpeg',
ImageFormat.jpeg => 'image/jpeg',
ImageFormat.gif => 'image/gif',
ImageFormat.bmp => 'image/bmp',
ImageFormat.webp => 'image/webp',
};

/// Builds an [XFile] from the given [imageData] and [fileName].
/// The [fileName] is used as the name of the file.
/// The file extension is determined by the [ImageFileType].
/// The file extension is determined by the [ImageFormat].
XFile buildXFile(Uint8List imageData, String fileName) => XFile.fromData(imageData, name: "$fileName.$extension");

/// Compares the given [extension] with the extension of this [ImageFormat] case-insensitive.
bool matches(String extension) => extension.toLowerCase() == this.extension.toLowerCase();
}
12 changes: 12 additions & 0 deletions lib/model/riverpod_states/introduction_state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,23 @@ class IntroductionState with _$IntroductionState {
return IntroductionState(completedIntroductions: newCompletedIntroductions);
}

IntroductionState withCompletedIntroductions(List<Introduction> values) {
final newCompletedIntroductions = {...completedIntroductions};
newCompletedIntroductions.addAll(values);
return IntroductionState(completedIntroductions: newCompletedIntroductions);
}

IntroductionState withoutCompletedIntroduction(Introduction introduction) {
final newCompletedIntroductions = {...completedIntroductions};
newCompletedIntroductions.remove(introduction);
return IntroductionState(completedIntroductions: newCompletedIntroductions);
}

IntroductionState withoutCompletedIntroductions(List<Introduction> values) {
final newCompletedIntroductions = {...completedIntroductions};
newCompletedIntroductions.removeAll(values);
return IntroductionState(completedIntroductions: newCompletedIntroductions);
}

factory IntroductionState.fromJson(Map<String, dynamic> json) => _$IntroductionStateFromJson(json);
}
18 changes: 9 additions & 9 deletions lib/model/widget_image.dart
Original file line number Diff line number Diff line change
Expand Up @@ -44,27 +44,27 @@ class Uint8ListConverter implements JsonConverter<Uint8List, String> {
@JsonSerializable()
@Uint8ListConverter()
class WidgetImage {
final ImageFileType fileType;
final ImageFormat imageFormat;
final Uint8List imageData;
final String fileName;

String get fullFileName => '$fileName.${fileType.extension}';
String get fullFileName => '$fileName.${imageFormat.extension}';

WidgetImage({
required this.fileName,
required this.fileType,
required this.imageFormat,
required this.imageData,
});

@override
String toString() {
return 'WidgetImage(fileName: $fileName, fileType: $fileType, imageData: $imageData)';
return 'WidgetImage(fileName: $fileName, imageFormat: $imageFormat, imageData: $imageData)';
}

@override
bool operator ==(Object other) => other is WidgetImage && other.fileType == fileType && other.imageData == imageData;
bool operator ==(Object other) => other is WidgetImage && other.imageFormat == imageFormat && other.imageData == imageData;
@override
int get hashCode => Object.hash(runtimeType, fileType, imageData);
int get hashCode => Object.hash(runtimeType, imageFormat, imageData);

Widget? _widget;
Widget get getWidget {
Expand All @@ -75,9 +75,9 @@ class WidgetImage {

Widget _buildImageWidget() {
try {
return fileType.buildImageWidget(imageData);
return imageFormat.buildImageWidget(imageData);
} catch (e) {
Logger.error('Image is not an ${fileType.typeName}, or the image data is corrupted.', error: e);
Logger.error('Image is not an ${imageFormat.name}, or the image data is corrupted.', error: e);
rethrow;
}
}
Expand All @@ -86,6 +86,6 @@ class WidgetImage {
Map<String, dynamic> toJson() => _$WidgetImageToJson(this);

XFile? toXFile() {
return fileType.buildXFile(imageData, fileName);
return imageFormat.buildXFile(imageData, fileName);
}
}
26 changes: 12 additions & 14 deletions lib/model/widget_image.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

38 changes: 17 additions & 21 deletions lib/utils/customization/application_customization.dart
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,9 @@ class ApplicationCustomization {
static const String appbarIconFileName = 'appbar_icon';
final WidgetImage splashScreenImage;
static const String splashScreenImageFileName = 'splash_screen_image';
final WidgetImage backgroundImage;
final WidgetImage? backgroundImage;
static const String backgroundImageFileName = 'background_image';
final WidgetImage licensesViewImage;
final WidgetImage? licensesViewImage;
static const String licensesViewImageFileName = 'licenses_view_image';

final ThemeCustomization lightTheme;
Expand All @@ -102,17 +102,17 @@ class ApplicationCustomization {
this.customFontBytes,
WidgetImage? appbarIcon,
WidgetImage? splashScreenImage,
WidgetImage? backgroundImage,
WidgetImage? licensesViewImage,
WidgetImage? Function()? backgroundImage,
this.licensesViewImage,
this.lightTheme = ThemeCustomization.defaultLightTheme,
this.darkTheme = ThemeCustomization.defaultDarkTheme,
this.disabledFeatures = const {},
}) : appbarIcon = appbarIcon ?? WidgetImage(fileType: ImageFileType.png, imageData: defaultIconUint8List, fileName: appbarIconFileName),
}) : appbarIcon = appbarIcon ?? WidgetImage(imageFormat: ImageFormat.png, imageData: defaultIconUint8List, fileName: appbarIconFileName),
splashScreenImage =
splashScreenImage ?? WidgetImage(fileType: ImageFileType.png, imageData: defaultImageUint8List, fileName: splashScreenImageFileName),
backgroundImage = backgroundImage ?? WidgetImage(fileType: ImageFileType.png, imageData: defaultImageUint8List, fileName: backgroundImageFileName),
licensesViewImage =
licensesViewImage ?? WidgetImage(fileType: ImageFileType.png, imageData: defaultImageUint8List, fileName: licensesViewImageFileName);
splashScreenImage ?? WidgetImage(imageFormat: ImageFormat.png, imageData: defaultImageUint8List, fileName: splashScreenImageFileName),
backgroundImage = backgroundImage != null
? backgroundImage()
: WidgetImage(imageFormat: ImageFormat.png, imageData: defaultImageUint8List, fileName: splashScreenImageFileName);

ApplicationCustomization copyWith({
String? appName,
Expand All @@ -123,8 +123,8 @@ class ApplicationCustomization {
String? feedbackSubjectPrefix,
WidgetImage? appbarIcon,
WidgetImage? splashScreenImage,
WidgetImage? backgroundImage,
WidgetImage? licensesViewImage,
WidgetImage? Function()? backgroundImage,
WidgetImage? Function()? licensesViewImage,
ThemeCustomization? lightTheme,
ThemeCustomization? darkTheme,
Set<AppFeature>? disabledFeatures,
Expand All @@ -140,8 +140,8 @@ class ApplicationCustomization {
customFontBytes: customFontBytes,
appbarIcon: appbarIcon ?? this.appbarIcon,
splashScreenImage: splashScreenImage ?? this.splashScreenImage,
backgroundImage: backgroundImage ?? this.backgroundImage,
licensesViewImage: licensesViewImage ?? this.licensesViewImage,
backgroundImage: backgroundImage ?? () => this.backgroundImage,
licensesViewImage: licensesViewImage != null ? licensesViewImage() : this.licensesViewImage,
lightTheme: lightTheme ?? this.lightTheme,
darkTheme: darkTheme ?? this.darkTheme,
disabledFeatures: disabledFeatures ?? this.disabledFeatures,
Expand Down Expand Up @@ -198,7 +198,7 @@ class ApplicationCustomization {
customFontBytes: fontBytes,
appbarIcon: appbarIcon,
splashScreenImage: splashScreenImage,
backgroundImage: backgroundImage,
backgroundImage: () => backgroundImage,
licensesViewImage: licensesViewImage,
lightTheme: lightTheme,
darkTheme: darkTheme,
Expand Down Expand Up @@ -238,11 +238,7 @@ class ApplicationCustomization {
: json['appImage'] != null
? WidgetImage.fromJson(json['appImage'] as Map<String, dynamic>)
: null,
backgroundImage: json['backgroundImage'] != null
? WidgetImage.fromJson(json['backgroundImage'] as Map<String, dynamic>)
: json['appImage'] != null
? WidgetImage.fromJson(json['appImage'] as Map<String, dynamic>)
: null,
backgroundImage: json.containsKey('backgroundImage') ? () => WidgetImage.fromJson(json['backgroundImage'] as Map<String, dynamic>) : () => null,
licensesViewImage: json['licensesViewImage'] != null
? WidgetImage.fromJson(json['licensesViewImage'] as Map<String, dynamic>)
: json['appImage'] != null
Expand All @@ -265,8 +261,8 @@ class ApplicationCustomization {
'customFontBytes': customFontBytes != null ? base64Encode(customFontBytes!) : null,
'appbarIcon': appbarIcon.toJson(),
'splashScreenImage': splashScreenImage.toJson(),
'backgroundImage': backgroundImage.toJson(),
'licensesViewImage': licensesViewImage.toJson(),
if (backgroundImage != null) 'backgroundImage': backgroundImage?.toJson(),
if (licensesViewImage != null) 'licensesViewImage': licensesViewImage?.toJson(),
'lightTheme': lightTheme.toJson(),
'darkTheme': darkTheme.toJson(),
'disabledFeatures': disabledFeatures.map((e) => e.name).toList(),
Expand Down
Loading

0 comments on commit c02aa4f

Please sign in to comment.