♻️ Replace the pattle_generator
This commit is contained in:
@@ -149,9 +149,9 @@ PODS:
|
|||||||
- flutter_udid (0.0.1):
|
- flutter_udid (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- SAMKeychain
|
- SAMKeychain
|
||||||
- flutter_webrtc (1.1.0):
|
- flutter_webrtc (1.2.0):
|
||||||
- Flutter
|
- Flutter
|
||||||
- WebRTC-SDK (= 137.7151.03)
|
- WebRTC-SDK (= 137.7151.04)
|
||||||
- gal (1.0.0):
|
- gal (1.0.0):
|
||||||
- Flutter
|
- Flutter
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
@@ -219,7 +219,7 @@ PODS:
|
|||||||
- livekit_client (2.5.0):
|
- livekit_client (2.5.0):
|
||||||
- Flutter
|
- Flutter
|
||||||
- flutter_webrtc
|
- flutter_webrtc
|
||||||
- WebRTC-SDK (= 137.7151.03)
|
- WebRTC-SDK (= 137.7151.04)
|
||||||
- local_auth_darwin (0.0.1):
|
- local_auth_darwin (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
@@ -299,7 +299,7 @@ PODS:
|
|||||||
- Flutter
|
- Flutter
|
||||||
- wakelock_plus (0.0.1):
|
- wakelock_plus (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- WebRTC-SDK (137.7151.03)
|
- WebRTC-SDK (137.7151.04)
|
||||||
|
|
||||||
DEPENDENCIES:
|
DEPENDENCIES:
|
||||||
- Alamofire
|
- Alamofire
|
||||||
@@ -499,7 +499,7 @@ SPEC CHECKSUMS:
|
|||||||
flutter_secure_storage: 1ed9476fba7e7a782b22888f956cce43e2c62f13
|
flutter_secure_storage: 1ed9476fba7e7a782b22888f956cce43e2c62f13
|
||||||
flutter_timezone: 7c838e17ffd4645d261e87037e5bebf6d38fe544
|
flutter_timezone: 7c838e17ffd4645d261e87037e5bebf6d38fe544
|
||||||
flutter_udid: f7c3884e6ec2951efe4f9de082257fc77c4d15e9
|
flutter_udid: f7c3884e6ec2951efe4f9de082257fc77c4d15e9
|
||||||
flutter_webrtc: b0b2e04411747142962164a1cfa43a1af9a0afac
|
flutter_webrtc: c3e21fc0dcd9d8eb246ae4d5256fcbeb2f5ecd22
|
||||||
gal: baecd024ebfd13c441269ca7404792a7152fde89
|
gal: baecd024ebfd13c441269ca7404792a7152fde89
|
||||||
GoogleAdsOnDeviceConversion: 9090c435cde08903e8dd1ba2c77fbec9e46d9afe
|
GoogleAdsOnDeviceConversion: 9090c435cde08903e8dd1ba2c77fbec9e46d9afe
|
||||||
GoogleAppMeasurement: 09f341dfa8527d1612a09cbfe809a242c0b737af
|
GoogleAppMeasurement: 09f341dfa8527d1612a09cbfe809a242c0b737af
|
||||||
@@ -508,8 +508,8 @@ SPEC CHECKSUMS:
|
|||||||
image_picker_ios: 7fe1ff8e34c1790d6fff70a32484959f563a928a
|
image_picker_ios: 7fe1ff8e34c1790d6fff70a32484959f563a928a
|
||||||
irondash_engine_context: 8e58ca8e0212ee9d1c7dc6a42121849986c88486
|
irondash_engine_context: 8e58ca8e0212ee9d1c7dc6a42121849986c88486
|
||||||
Kingfisher: ff0d31a1f07bdff6a1ebb3ba08b8e6e567b6500c
|
Kingfisher: ff0d31a1f07bdff6a1ebb3ba08b8e6e567b6500c
|
||||||
livekit_client: f810c81bbbc229a84f60b09e66603ac4e93f7599
|
livekit_client: a6f5fa86ac28ccd7ded53626a5379961db311ab4
|
||||||
local_auth_darwin: d2e8c53ef0c4f43c646462e3415432c4dab3ae19
|
local_auth_darwin: c3ee6cce0a8d56be34c8ccb66ba31f7f180aaebb
|
||||||
media_kit_libs_ios_video: 5a18affdb97d1f5d466dc79988b13eff6c5e2854
|
media_kit_libs_ios_video: 5a18affdb97d1f5d466dc79988b13eff6c5e2854
|
||||||
media_kit_video: 1746e198cb697d1ffb734b1d05ec429d1fcd1474
|
media_kit_video: 1746e198cb697d1ffb734b1d05ec429d1fcd1474
|
||||||
nanopb: fad817b59e0457d11a5dfbde799381cd727c1275
|
nanopb: fad817b59e0457d11a5dfbde799381cd727c1275
|
||||||
@@ -536,7 +536,7 @@ SPEC CHECKSUMS:
|
|||||||
url_launcher_ios: 694010445543906933d732453a59da0a173ae33d
|
url_launcher_ios: 694010445543906933d732453a59da0a173ae33d
|
||||||
volume_controller: 3657a1f65bedb98fa41ff7dc5793537919f31b12
|
volume_controller: 3657a1f65bedb98fa41ff7dc5793537919f31b12
|
||||||
wakelock_plus: e29112ab3ef0b318e58cfa5c32326458be66b556
|
wakelock_plus: e29112ab3ef0b318e58cfa5c32326458be66b556
|
||||||
WebRTC-SDK: 69d4e56b0b4b27d788e87bab9b9a1326ed05b1e3
|
WebRTC-SDK: 40d4f5ba05cadff14e4db5614aec402a633f007e
|
||||||
|
|
||||||
PODFILE CHECKSUM: c818292390b02fa379036ea099713a332bd7193f
|
PODFILE CHECKSUM: c818292390b02fa379036ea099713a332bd7193f
|
||||||
|
|
||||||
|
@@ -32,7 +32,7 @@ import 'package:island/widgets/content/cloud_files.dart';
|
|||||||
import 'package:island/widgets/content/markdown.dart';
|
import 'package:island/widgets/content/markdown.dart';
|
||||||
import 'package:island/widgets/safety/abuse_report_helper.dart';
|
import 'package:island/widgets/safety/abuse_report_helper.dart';
|
||||||
import 'package:material_symbols_icons/symbols.dart';
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
import 'package:palette_generator/palette_generator.dart';
|
import 'package:island/services/color_extraction.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
import 'package:share_plus/share_plus.dart';
|
import 'package:share_plus/share_plus.dart';
|
||||||
import 'package:styled_widget/styled_widget.dart';
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
@@ -581,14 +581,14 @@ Future<Color?> accountAppbarForcegroundColor(Ref ref, String uname) async {
|
|||||||
try {
|
try {
|
||||||
final account = await ref.watch(accountProvider(uname).future);
|
final account = await ref.watch(accountProvider(uname).future);
|
||||||
if (account.profile.background == null) return null;
|
if (account.profile.background == null) return null;
|
||||||
final palette = await PaletteGenerator.fromImageProvider(
|
final colors = await ColorExtractionService.getColorsFromImage(
|
||||||
CloudImageWidget.provider(
|
CloudImageWidget.provider(
|
||||||
fileId: account.profile.background!.id,
|
fileId: account.profile.background!.id,
|
||||||
serverUrl: ref.watch(serverUrlProvider),
|
serverUrl: ref.watch(serverUrlProvider),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
final dominantColor = palette.dominantColor?.color;
|
if (colors.isEmpty) return null;
|
||||||
if (dominantColor == null) return null;
|
final dominantColor = colors.first;
|
||||||
return dominantColor.computeLuminance() > 0.5 ? Colors.black : Colors.white;
|
return dominantColor.computeLuminance() > 0.5 ? Colors.black : Colors.white;
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
return null;
|
return null;
|
||||||
|
@@ -21,7 +21,7 @@ import 'package:island/widgets/content/cloud_files.dart';
|
|||||||
import 'package:island/widgets/content/markdown.dart';
|
import 'package:island/widgets/content/markdown.dart';
|
||||||
import 'package:island/widgets/post/post_list.dart';
|
import 'package:island/widgets/post/post_list.dart';
|
||||||
import 'package:material_symbols_icons/symbols.dart';
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
import 'package:palette_generator/palette_generator.dart';
|
import 'package:island/services/color_extraction.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
import 'package:styled_widget/styled_widget.dart';
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
|
|
||||||
@@ -278,14 +278,14 @@ Future<Color?> publisherAppbarForcegroundColor(Ref ref, String pubName) async {
|
|||||||
try {
|
try {
|
||||||
final publisher = await ref.watch(publisherProvider(pubName).future);
|
final publisher = await ref.watch(publisherProvider(pubName).future);
|
||||||
if (publisher.background == null) return null;
|
if (publisher.background == null) return null;
|
||||||
final palette = await PaletteGenerator.fromImageProvider(
|
final colors = await ColorExtractionService.getColorsFromImage(
|
||||||
CloudImageWidget.provider(
|
CloudImageWidget.provider(
|
||||||
fileId: publisher.background!.id,
|
fileId: publisher.background!.id,
|
||||||
serverUrl: ref.watch(serverUrlProvider),
|
serverUrl: ref.watch(serverUrlProvider),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
final dominantColor = palette.dominantColor?.color;
|
if (colors.isEmpty) return null;
|
||||||
if (dominantColor == null) return null;
|
final dominantColor = colors.first;
|
||||||
return dominantColor.computeLuminance() > 0.5 ? Colors.black : Colors.white;
|
return dominantColor.computeLuminance() > 0.5 ? Colors.black : Colors.white;
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
return null;
|
return null;
|
||||||
|
@@ -8,7 +8,7 @@ import 'package:island/services/responsive.dart';
|
|||||||
import 'package:island/widgets/account/account_pfc.dart';
|
import 'package:island/widgets/account/account_pfc.dart';
|
||||||
import 'package:island/widgets/account/status.dart';
|
import 'package:island/widgets/account/status.dart';
|
||||||
import 'package:island/widgets/post/post_list.dart';
|
import 'package:island/widgets/post/post_list.dart';
|
||||||
import 'package:palette_generator/palette_generator.dart';
|
import 'package:island/services/color_extraction.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
import 'package:gap/gap.dart';
|
import 'package:gap/gap.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
@@ -32,14 +32,14 @@ part 'realm_detail.g.dart';
|
|||||||
Future<Color?> realmAppbarForegroundColor(Ref ref, String realmSlug) async {
|
Future<Color?> realmAppbarForegroundColor(Ref ref, String realmSlug) async {
|
||||||
final realm = await ref.watch(realmProvider(realmSlug).future);
|
final realm = await ref.watch(realmProvider(realmSlug).future);
|
||||||
if (realm?.background == null) return null;
|
if (realm?.background == null) return null;
|
||||||
final palette = await PaletteGenerator.fromImageProvider(
|
final colors = await ColorExtractionService.getColorsFromImage(
|
||||||
CloudImageWidget.provider(
|
CloudImageWidget.provider(
|
||||||
fileId: realm!.background!.id,
|
fileId: realm!.background!.id,
|
||||||
serverUrl: ref.watch(serverUrlProvider),
|
serverUrl: ref.watch(serverUrlProvider),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
final dominantColor = palette.dominantColor?.color;
|
if (colors.isEmpty) return null;
|
||||||
if (dominantColor == null) return null;
|
final dominantColor = colors.first;
|
||||||
return dominantColor.computeLuminance() > 0.5 ? Colors.black : Colors.white;
|
return dominantColor.computeLuminance() > 0.5 ? Colors.black : Colors.white;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -12,11 +12,11 @@ import 'package:flutter_hooks/flutter_hooks.dart';
|
|||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:image_picker/image_picker.dart';
|
import 'package:image_picker/image_picker.dart';
|
||||||
import 'package:island/pods/network.dart';
|
import 'package:island/pods/network.dart';
|
||||||
|
import 'package:island/services/color_extraction.dart';
|
||||||
import 'package:island/services/responsive.dart';
|
import 'package:island/services/responsive.dart';
|
||||||
import 'package:island/widgets/alert.dart';
|
import 'package:island/widgets/alert.dart';
|
||||||
import 'package:island/widgets/app_scaffold.dart';
|
import 'package:island/widgets/app_scaffold.dart';
|
||||||
import 'package:material_symbols_icons/symbols.dart';
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
import 'package:palette_generator/palette_generator.dart';
|
|
||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
import 'package:styled_widget/styled_widget.dart';
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
import 'package:island/pods/config.dart';
|
import 'package:island/pods/config.dart';
|
||||||
@@ -293,24 +293,26 @@ class SettingsScreen extends HookConsumerWidget {
|
|||||||
trailing: const Icon(Symbols.chevron_right),
|
trailing: const Icon(Symbols.chevron_right),
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
showLoadingModal(context);
|
showLoadingModal(context);
|
||||||
final palette = await PaletteGenerator.fromImageProvider(
|
final colors = await ColorExtractionService.getColorsFromImage(
|
||||||
FileImage(
|
FileImage(
|
||||||
File('${docBasepath.value}/$kAppBackgroundImagePath'),
|
File('${docBasepath.value}/$kAppBackgroundImagePath'),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
if (palette.darkVibrantColor == null ||
|
if (colors.isEmpty) {
|
||||||
palette.lightVibrantColor == null) {
|
|
||||||
if (context.mounted) hideLoadingModal(context);
|
if (context.mounted) hideLoadingModal(context);
|
||||||
showErrorAlert(
|
showErrorAlert(
|
||||||
'Unable to calculate the domiant color of the background image.',
|
'Unable to calculate the dominant color of the background image.',
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!context.mounted) return;
|
if (!context.mounted) return;
|
||||||
|
final colorScheme = ColorScheme.fromSeed(
|
||||||
|
seedColor: colors.first,
|
||||||
|
);
|
||||||
final color =
|
final color =
|
||||||
MediaQuery.of(context).platformBrightness == Brightness.dark
|
MediaQuery.of(context).platformBrightness == Brightness.dark
|
||||||
? palette.darkVibrantColor!.color
|
? colorScheme.primary
|
||||||
: palette.lightVibrantColor!.color;
|
: colorScheme.primary;
|
||||||
ref
|
ref
|
||||||
.read(appSettingsNotifierProvider.notifier)
|
.read(appSettingsNotifierProvider.notifier)
|
||||||
.setAppColorScheme(color.value);
|
.setAppColorScheme(color.value);
|
||||||
|
49
lib/services/color_extraction.dart
Normal file
49
lib/services/color_extraction.dart
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
import 'package:flutter/widgets.dart';
|
||||||
|
import 'package:image/image.dart' as img;
|
||||||
|
import 'package:material_color_utilities/material_color_utilities.dart' as mcu;
|
||||||
|
|
||||||
|
class ColorExtractionService {
|
||||||
|
/// Extracts dominant colors from an image provider.
|
||||||
|
/// Returns a list of colors suitable for UI theming.
|
||||||
|
static Future<List<Color>> getColorsFromImage(ImageProvider provider) async {
|
||||||
|
try {
|
||||||
|
if (provider is FileImage) {
|
||||||
|
final bytes = await provider.file.readAsBytes();
|
||||||
|
final image = img.decodeImage(bytes);
|
||||||
|
if (image == null) return [];
|
||||||
|
final Map<int, int> colorToCount = {};
|
||||||
|
for (int y = 0; y < image.height; y++) {
|
||||||
|
for (int x = 0; x < image.width; x++) {
|
||||||
|
final pixel = image.getPixel(x, y) as int;
|
||||||
|
final r = (pixel >> 24) & 0xff;
|
||||||
|
final g = (pixel >> 16) & 0xff;
|
||||||
|
final b = (pixel >> 8) & 0xff;
|
||||||
|
final a = pixel & 0xff;
|
||||||
|
if (a == 0) continue;
|
||||||
|
final argb = (a << 24) | (r << 16) | (g << 8) | b;
|
||||||
|
colorToCount[argb] = (colorToCount[argb] ?? 0) + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
final List<int> filteredResults = mcu.Score.score(
|
||||||
|
colorToCount,
|
||||||
|
desired: 1,
|
||||||
|
filter: true,
|
||||||
|
);
|
||||||
|
final List<int> scoredResults = mcu.Score.score(
|
||||||
|
colorToCount,
|
||||||
|
desired: 4,
|
||||||
|
filter: false,
|
||||||
|
);
|
||||||
|
return <dynamic>{
|
||||||
|
...filteredResults,
|
||||||
|
...scoredResults,
|
||||||
|
}.toList().map((argb) => Color(argb)).toList();
|
||||||
|
} else {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
debugPrint('Error getting colors from image: $e');
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
10
pubspec.lock
10
pubspec.lock
@@ -1270,7 +1270,7 @@ packages:
|
|||||||
source: hosted
|
source: hosted
|
||||||
version: "4.1.2"
|
version: "4.1.2"
|
||||||
image:
|
image:
|
||||||
dependency: transitive
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: image
|
name: image
|
||||||
sha256: "4e973fcf4caae1a4be2fa0a13157aa38a8f9cb049db6529aa00b4d71abc4d928"
|
sha256: "4e973fcf4caae1a4be2fa0a13157aa38a8f9cb049db6529aa00b4d71abc4d928"
|
||||||
@@ -1717,14 +1717,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.2.1"
|
version: "3.2.1"
|
||||||
palette_generator:
|
|
||||||
dependency: "direct main"
|
|
||||||
description:
|
|
||||||
name: palette_generator
|
|
||||||
sha256: "4420f7ccc3f0a4a906144e73f8b6267cd940b64f57a7262e95cb8cec3a8ae0ed"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "0.3.3+7"
|
|
||||||
pasteboard:
|
pasteboard:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
@@ -106,10 +106,11 @@ dependencies:
|
|||||||
livekit_client: ^2.5.1
|
livekit_client: ^2.5.1
|
||||||
pasteboard: ^0.4.0
|
pasteboard: ^0.4.0
|
||||||
flutter_colorpicker: ^1.1.0
|
flutter_colorpicker: ^1.1.0
|
||||||
|
image: ^4.2.0
|
||||||
record: ^6.1.1
|
record: ^6.1.1
|
||||||
qr_flutter: ^4.1.0
|
qr_flutter: ^4.1.0
|
||||||
flutter_otp_text_field: ^1.5.1+1
|
flutter_otp_text_field: ^1.5.1+1
|
||||||
palette_generator: ^0.3.3+7
|
|
||||||
flutter_popup_card: ^0.0.6
|
flutter_popup_card: ^0.0.6
|
||||||
timezone: ^0.10.1
|
timezone: ^0.10.1
|
||||||
flutter_timezone: ^5.0.0
|
flutter_timezone: ^5.0.0
|
||||||
|
Reference in New Issue
Block a user