info: color palette
This commit is contained in:
parent
fc9d282caa
commit
5b2fbe48d3
4 changed files with 98 additions and 5 deletions
|
@ -8,6 +8,7 @@ All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
- Cataloguing: identify Apple variant of HDR images
|
- Cataloguing: identify Apple variant of HDR images
|
||||||
- Collection: allow using hash (md5/sha1/sha256) when bulk renaming
|
- Collection: allow using hash (md5/sha1/sha256) when bulk renaming
|
||||||
|
- Info: color palette
|
||||||
- option to force using western arabic numerals for dates
|
- option to force using western arabic numerals for dates
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
|
@ -47,6 +47,7 @@ class AIcons {
|
||||||
static const mainStorage = Icons.smartphone_outlined;
|
static const mainStorage = Icons.smartphone_outlined;
|
||||||
static const mimeType = Icons.code_outlined;
|
static const mimeType = Icons.code_outlined;
|
||||||
static const opacity = Icons.opacity;
|
static const opacity = Icons.opacity;
|
||||||
|
static const palette = Icons.palette_outlined;
|
||||||
static final privacy = MdiIcons.shieldAccountOutline;
|
static final privacy = MdiIcons.shieldAccountOutline;
|
||||||
static const rating = Icons.star_border_outlined;
|
static const rating = Icons.star_border_outlined;
|
||||||
static const ratingFull = Icons.star;
|
static const ratingFull = Icons.star;
|
||||||
|
|
87
lib/widgets/viewer/info/color_section.dart
Normal file
87
lib/widgets/viewer/info/color_section.dart
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
import 'dart:async';
|
||||||
|
import 'dart:math';
|
||||||
|
|
||||||
|
import 'package:aves/model/entry/entry.dart';
|
||||||
|
import 'package:aves/model/entry/extensions/images.dart';
|
||||||
|
import 'package:aves/theme/durations.dart';
|
||||||
|
import 'package:aves/theme/icons.dart';
|
||||||
|
import 'package:aves/widgets/common/basic/color_indicator.dart';
|
||||||
|
import 'package:aves/widgets/viewer/info/common.dart';
|
||||||
|
import 'package:flex_color_picker/flex_color_picker.dart' as flex;
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/scheduler.dart';
|
||||||
|
import 'package:flutter_staggered_animations/flutter_staggered_animations.dart';
|
||||||
|
import 'package:palette_generator/palette_generator.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
class ColorSectionSliver extends StatefulWidget {
|
||||||
|
final AvesEntry entry;
|
||||||
|
|
||||||
|
const ColorSectionSliver({super.key, required this.entry});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<ColorSectionSliver> createState() => _ColorSectionSliverState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ColorSectionSliverState extends State<ColorSectionSliver> {
|
||||||
|
late final Future<PaletteGenerator> _paletteLoader;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
final provider = widget.entry.getThumbnail(extent: min(200, widget.entry.displaySize.longestSide));
|
||||||
|
_paletteLoader = PaletteGenerator.fromImageProvider(
|
||||||
|
provider,
|
||||||
|
maximumColorCount: 10,
|
||||||
|
// do not use the default palette filter
|
||||||
|
filters: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return SliverToBoxAdapter(
|
||||||
|
child: FutureBuilder<PaletteGenerator>(
|
||||||
|
future: _paletteLoader,
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
final colors = snapshot.data?.paletteColors;
|
||||||
|
if (colors == null || colors.isEmpty) return const SizedBox();
|
||||||
|
|
||||||
|
final durations = context.watch<DurationsData>();
|
||||||
|
return Wrap(
|
||||||
|
alignment: WrapAlignment.center,
|
||||||
|
children: AnimationConfiguration.toStaggeredList(
|
||||||
|
duration: durations.staggeredAnimation,
|
||||||
|
delay: durations.staggeredAnimationDelay * timeDilation,
|
||||||
|
childAnimationBuilder: (child) => SlideAnimation(
|
||||||
|
verticalOffset: 50.0,
|
||||||
|
child: FadeInAnimation(
|
||||||
|
child: child,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
children: [
|
||||||
|
const SectionRow(icon: AIcons.palette),
|
||||||
|
...colors.map(
|
||||||
|
(v) => Padding(
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
child: Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
ColorIndicator(value: v.color),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
SelectableText(
|
||||||
|
'#${v.color.hex}',
|
||||||
|
style: const TextStyle(fontFamily: 'monospace'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,6 +17,7 @@ import 'package:aves/widgets/viewer/info/basic_section.dart';
|
||||||
import 'package:aves/widgets/viewer/info/embedded/embedded_data_opener.dart';
|
import 'package:aves/widgets/viewer/info/embedded/embedded_data_opener.dart';
|
||||||
import 'package:aves/widgets/viewer/info/info_app_bar.dart';
|
import 'package:aves/widgets/viewer/info/info_app_bar.dart';
|
||||||
import 'package:aves/widgets/viewer/info/location_section.dart';
|
import 'package:aves/widgets/viewer/info/location_section.dart';
|
||||||
|
import 'package:aves/widgets/viewer/info/color_section.dart';
|
||||||
import 'package:aves/widgets/viewer/info/metadata/metadata_dir.dart';
|
import 'package:aves/widgets/viewer/info/metadata/metadata_dir.dart';
|
||||||
import 'package:aves/widgets/viewer/info/metadata/metadata_section.dart';
|
import 'package:aves/widgets/viewer/info/metadata/metadata_section.dart';
|
||||||
import 'package:aves/widgets/viewer/multipage/conductor.dart';
|
import 'package:aves/widgets/viewer/multipage/conductor.dart';
|
||||||
|
@ -233,10 +234,6 @@ class _InfoPageContentState extends State<_InfoPageContent> {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
final metadataSliver = MetadataSectionSliver(
|
|
||||||
entry: entry,
|
|
||||||
metadataNotifier: _metadataNotifier,
|
|
||||||
);
|
|
||||||
|
|
||||||
return NotificationListener<FilterNotification>(
|
return NotificationListener<FilterNotification>(
|
||||||
onNotification: (notification) {
|
onNotification: (notification) {
|
||||||
|
@ -262,7 +259,14 @@ class _InfoPageContentState extends State<_InfoPageContent> {
|
||||||
),
|
),
|
||||||
SliverPadding(
|
SliverPadding(
|
||||||
padding: horizontalPadding + const EdgeInsets.only(bottom: 8),
|
padding: horizontalPadding + const EdgeInsets.only(bottom: 8),
|
||||||
sliver: metadataSliver,
|
sliver: MetadataSectionSliver(
|
||||||
|
entry: entry,
|
||||||
|
metadataNotifier: _metadataNotifier,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SliverPadding(
|
||||||
|
padding: horizontalPadding + const EdgeInsets.only(bottom: 8),
|
||||||
|
sliver: ColorSectionSliver(entry: entry),
|
||||||
),
|
),
|
||||||
const BottomPaddingSliver(),
|
const BottomPaddingSliver(),
|
||||||
],
|
],
|
||||||
|
|
Loading…
Reference in a new issue