minor fixes

This commit is contained in:
Thibault Deckers 2022-12-21 18:26:44 +01:00
parent abca3644f5
commit 1ef9d75b0b
10 changed files with 101 additions and 48 deletions

View file

@ -22,7 +22,7 @@ import 'package:fijkplayer/fijkplayer.dart';
import 'package:flutter/foundation.dart';
class VideoMetadataFormatter {
static final _dateY4M2D2H2m2s2Pattern = RegExp(r'(\d{4})[-./](\d{1,2})[-./](\d{1,2})([ T](\d{1,2}):(\d{1,2}):(\d{1,2})( ([ap]\.? ?m\.?))?)?');
static final _dateY4M2D2H2m2s2Pattern = RegExp(r'(\d{4})[-./:](\d{1,2})[-./:](\d{1,2})([ T](\d{1,2}):(\d{1,2}):(\d{1,2})( ([ap]\.? ?m\.?))?)?');
static final _ambiguousDatePatterns = {
RegExp(r'^\d{2}[-/]\d{2}[-/]\d{4}$'),
};
@ -127,6 +127,7 @@ class VideoMetadataFormatter {
// - `2022-01-28T5:07:46 p. m.Z`
// - `2012-1-1T12:00:00Z`
// - `2020.10.14`
// - `2016:11:16 18:00:00`
// - `2021` (not enough to build a date)
var match = _dateY4M2D2H2m2s2Pattern.firstMatch(dateString);

View file

@ -165,6 +165,7 @@ class _CollectionAppBarState extends State<CollectionAppBar> with SingleTickerPr
builder: (context, _, child) {
final isTelevision = device.isTelevision;
final actions = _buildActions(context, selection);
final onFilterTap = removableFilters ? collection.removeFilter : null;
return AvesAppBar(
contentHeight: appBarContentHeight,
leading: _buildAppBarLeading(
@ -192,8 +193,8 @@ class _CollectionAppBarState extends State<CollectionAppBar> with SingleTickerPr
},
child: FilterBar(
filters: visibleFilters,
removable: removableFilters,
onTap: removableFilters ? collection.removeFilter : null,
onTap: onFilterTap,
onRemove: onFilterTap,
),
),
if (queryEnabled)

View file

@ -11,14 +11,13 @@ class FilterBar extends StatefulWidget {
static const double preferredHeight = AvesFilterChip.minChipHeight + verticalPadding;
final List<CollectionFilter> filters;
final bool removable;
final FilterCallback? onTap;
final FilterCallback? onTap, onRemove;
FilterBar({
super.key,
required Set<CollectionFilter> filters,
this.removable = false,
this.onTap,
this.onRemove,
}) : filters = List<CollectionFilter>.from(filters)..sort();
@override
@ -31,8 +30,6 @@ class _FilterBarState extends State<FilterBar> {
List<CollectionFilter> get filters => widget.filters;
FilterCallback? get onTap => widget.onTap;
@override
void didUpdateWidget(covariant FilterBar oldWidget) {
super.didUpdateWidget(oldWidget);
@ -104,30 +101,37 @@ class _FilterBarState extends State<FilterBar> {
}
Widget _buildChip(CollectionFilter filter) {
final onTap = widget.onTap != null
? (filter) {
_userTappedFilter = filter;
widget.onTap?.call(filter);
}
: null;
final onRemove = widget.onRemove != null
? (filter) {
_userTappedFilter = filter;
widget.onRemove?.call(filter);
}
: null;
return _Chip(
filter: filter,
removable: widget.removable,
single: filters.length == 1,
onTap: onTap != null
? (filter) {
_userTappedFilter = filter;
onTap!(filter);
}
: null,
onTap: onTap,
onRemove: onRemove,
);
}
}
class _Chip extends StatelessWidget {
final CollectionFilter filter;
final bool removable, single;
final FilterCallback? onTap;
final bool single;
final FilterCallback? onTap, onRemove;
const _Chip({
required this.filter,
required this.removable,
required this.single,
required this.onTap,
required this.onRemove,
});
@override
@ -138,7 +142,6 @@ class _Chip extends StatelessWidget {
child: AvesFilterChip(
key: ValueKey(filter),
filter: filter,
removable: removable,
maxWidth: single
? AvesFilterChip.computeMaxWidth(
context,
@ -149,6 +152,7 @@ class _Chip extends StatelessWidget {
: null,
heroType: HeroType.always,
onTap: onTap,
onRemove: onRemove,
),
),
);

View file

@ -67,10 +67,11 @@ class TitledExpandableFilterRow extends StatelessWidget {
class ExpandableFilterRow extends StatelessWidget {
final List<CollectionFilter> filters;
final bool isExpanded;
final bool removable, showGenericIcon;
final bool showGenericIcon;
final Widget? Function(CollectionFilter)? leadingBuilder;
final HeroType Function(CollectionFilter filter)? heroTypeBuilder;
final FilterCallback onTap;
final FilterCallback? onRemove;
final OffsetFilterCallback? onLongPress;
static const double horizontalPadding = 8;
@ -80,11 +81,11 @@ class ExpandableFilterRow extends StatelessWidget {
super.key,
required this.filters,
required this.isExpanded,
this.removable = false,
this.showGenericIcon = true,
this.leadingBuilder,
this.heroTypeBuilder,
required this.onTap,
this.onRemove,
required this.onLongPress,
});
@ -143,11 +144,11 @@ class ExpandableFilterRow extends StatelessWidget {
// key `album-{path}` is expected by test driver
key: Key(filter.key),
filter: filter,
removable: removable,
showGenericIcon: showGenericIcon,
leadingOverride: leadingBuilder?.call(filter),
heroType: heroTypeBuilder?.call(filter) ?? HeroType.onTap,
onTap: onTap,
onRemove: onRemove,
onLongPress: onLongPress,
);
}

View file

@ -1,5 +1,6 @@
import 'package:aves/model/device.dart';
import 'package:aves/model/settings/settings.dart';
import 'package:aves/theme/colors.dart';
import 'package:aves/theme/durations.dart';
import 'package:aves/widgets/aves_app.dart';
import 'package:aves/widgets/common/fx/blurred.dart';
@ -63,7 +64,7 @@ class AvesAppBar extends StatelessWidget {
: const SizedBox(width: 16),
Expanded(
child: DefaultTextStyle(
style: Theme.of(context).appBarTheme.titleTextStyle!,
style: context.select<AvesColorsData, TextStyle>((v) => Theme.of(context).appBarTheme.titleTextStyle!),
child: Hero(
tag: titleHeroTag,
flightShuttleBuilder: _flightShuttleBuilder,

View file

@ -44,14 +44,14 @@ class AvesFilterDecoration {
class AvesFilterChip extends StatefulWidget {
final CollectionFilter filter;
final bool removable, showText, showGenericIcon, useFilterColor;
final bool showText, showGenericIcon, useFilterColor;
final AvesFilterDecoration? decoration;
final String? banner;
final Widget? leadingOverride, details;
final double padding;
final double? maxWidth;
final HeroType heroType;
final FilterCallback? onTap;
final FilterCallback? onTap, onRemove;
final OffsetFilterCallback? onLongPress;
static const double defaultRadius = 32;
@ -65,7 +65,6 @@ class AvesFilterChip extends StatefulWidget {
const AvesFilterChip({
super.key,
required this.filter,
this.removable = false,
this.showText = true,
this.showGenericIcon = true,
this.useFilterColor = true,
@ -77,6 +76,7 @@ class AvesFilterChip extends StatefulWidget {
this.maxWidth,
this.heroType = HeroType.onTap,
this.onTap,
this.onRemove,
this.onLongPress = showDefaultLongPressMenu,
});
@ -154,10 +154,6 @@ class _AvesFilterChipState extends State<AvesFilterChip> {
double get padding => widget.padding;
FilterCallback? get onTap => widget.onTap;
OffsetFilterCallback? get onLongPress => widget.onLongPress;
@override
void initState() {
super.initState();
@ -219,12 +215,40 @@ class _AvesFilterChipState extends State<AvesFilterChip> {
final decoration = widget.decoration;
final chipBackground = Theme.of(context).scaffoldBackgroundColor;
final onTap = widget.onTap != null
? () {
WidgetsBinding.instance.addPostFrameCallback((_) => widget.onTap?.call(filter));
setState(() => _tapped = true);
}
: null;
final onRemove = widget.onRemove != null
? () {
WidgetsBinding.instance.addPostFrameCallback((_) => widget.onRemove?.call(filter));
setState(() => _tapped = true);
}
: null;
final onLongPress = widget.onLongPress != null
? () {
if (_tapPosition != null) {
widget.onLongPress?.call(context, filter, _tapPosition!);
}
}
: null;
Widget? content;
if (widget.showText) {
final textScaleFactor = MediaQuery.textScaleFactorOf(context);
final iconSize = AvesFilterChip.iconSize * textScaleFactor;
final leading = widget.leadingOverride ?? filter.iconBuilder(context, iconSize, showGenericIcon: widget.showGenericIcon);
final trailing = widget.removable ? Icon(AIcons.clear, size: iconSize) : null;
final trailing = onRemove != null
? IconButton(
icon: Icon(AIcons.clear, size: iconSize),
padding: EdgeInsets.zero,
splashRadius: IconTheme.of(context).size,
constraints: const BoxConstraints(),
onPressed: onRemove,
)
: null;
content = Row(
mainAxisSize: decoration != null ? MainAxisSize.max : MainAxisSize.min,
@ -317,13 +341,8 @@ class _AvesFilterChipState extends State<AvesFilterChip> {
// as of Flutter v2.8.0, `InkWell` does not have `onLongPressStart` like `GestureDetector`,
// so we get the long press details from the tap instead
onTapDown: onLongPress != null ? (details) => _tapPosition = details.globalPosition : null,
onTap: onTap != null
? () {
WidgetsBinding.instance.addPostFrameCallback((_) => onTap!(filter));
setState(() => _tapped = true);
}
: null,
onLongPress: onLongPress != null ? () => onLongPress!(context, filter, _tapPosition!) : null,
onTap: onTap,
onLongPress: onLongPress,
borderRadius: borderRadius,
child: FutureBuilder<Color>(
future: _colorFuture,

View file

@ -150,14 +150,16 @@ class _TagEditorPageState extends State<TagEditorPage> {
secondChild: ExpandableFilterRow(
filters: sortedTags.map((kv) => kv.key).toList(),
isExpanded: context.select<Settings, bool>((v) => v.tagEditorCurrentFilterSectionExpanded),
removable: true,
showGenericIcon: false,
leadingBuilder: showCount
? (filter) => _TagCount(
count: sortedTags.firstWhere((kv) => kv.key == filter).value,
)
: null,
onTap: _removeTag,
onTap: (filter) {
// TODO TLAD [#453]
},
onRemove: _removeTag,
onLongPress: null,
),
crossFadeState: sortedTags.isEmpty ? CrossFadeState.showFirst : CrossFadeState.showSecond,

View file

@ -88,14 +88,15 @@ class _HiddenFilters extends StatelessWidget {
child: Wrap(
spacing: 8,
runSpacing: 8,
children: filterList
.map((filter) => AvesFilterChip(
filter: filter,
removable: true,
onTap: (filter) => settings.changeFilterVisibility({filter}, true),
onLongPress: null,
))
.toList(),
children: filterList.map((filter) {
void onRemove(CollectionFilter filter) => settings.changeFilterVisibility({filter}, true);
return AvesFilterChip(
filter: filter,
onTap: onRemove,
onRemove: onRemove,
onLongPress: null,
);
}).toList(),
),
),
],

22
scripts/extract_apks.sh Executable file
View file

@ -0,0 +1,22 @@
#!/bin/bash
if [ ! -d "scripts" ]; then
cd ..
fi
BUNDLE="/home/tibo/Downloads/app-play-release.aab"
# shellcheck disable=SC2001
OUTPUT=$(sed "s|\.aab|\.apks|" <<<"$BUNDLE")
KEYS_PATH="android/key.properties"
STORE_PATH=$(sed -n 's|.*storeFile=\(.*\)[\r\n]|\1|p' "$KEYS_PATH")
# shellcheck disable=SC1003
STORE_PW=$(sed -n 's|.*storePassword=\(.*\)[\r\n]|\1|p' "$KEYS_PATH" | sed 's|\\'\''|'\''|g')
KEY_ALIAS=$(sed -n 's|.*keyAlias=\(.*\)[\r\n]|\1|p' "$KEYS_PATH")
# shellcheck disable=SC1003
KEY_PW=$(sed -n 's|.*keyPassword=\(.*\)[\r\n]|\1|p' "$KEYS_PATH" | sed 's|\\'\''|'\''|g')
echo "$BUNDLE -> $OUTPUT"
bundletool build-apks --bundle="$BUNDLE" --output="$OUTPUT" \
--ks="$STORE_PATH" --ks-pass="pass:$STORE_PW" \
--ks-key-alias="$KEY_ALIAS" --key-pass="pass:$KEY_PW"

View file

@ -16,6 +16,7 @@ void main() {
expect(VideoMetadataFormatter.parseVideoDate('2022-01-28T5:07:46 p. m.Z'), DateTime(2022, 1, 28, 17, 7, 46).millisecondsSinceEpoch);
expect(VideoMetadataFormatter.parseVideoDate('2012-1-1T12:00:00Z'), DateTime(2012, 1, 1, 12, 0, 0).millisecondsSinceEpoch);
expect(VideoMetadataFormatter.parseVideoDate('2020.10.14'), DateTime(2020, 10, 14).millisecondsSinceEpoch);
expect(VideoMetadataFormatter.parseVideoDate('2016:11:16 18:00:00'), DateTime(2016, 11, 16, 18, 0, 0).millisecondsSinceEpoch);
});
test('Ambiguous date', () {