Skip to content

Commit 3124cae

Browse files
Tomasz KądziołkaTomasz Kądziołka
authored andcommitted
Finished design of action bar
1 parent 6576ad2 commit 3124cae

File tree

7 files changed

+73
-18
lines changed

7 files changed

+73
-18
lines changed

app/src/main/java/pl/tkadziolka/snipmeandroid/bridge/main/MainModelPlugin.kt

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,7 @@ import org.koin.core.component.inject
99
import pl.tkadziolka.snipmeandroid.bridge.Bridge
1010
import pl.tkadziolka.snipmeandroid.bridge.ModelPlugin
1111
import pl.tkadziolka.snipmeandroid.domain.reaction.UserReaction
12-
import pl.tkadziolka.snipmeandroid.domain.snippets.Owner
13-
import pl.tkadziolka.snipmeandroid.domain.snippets.Snippet
14-
import pl.tkadziolka.snipmeandroid.domain.snippets.SnippetCode
15-
import pl.tkadziolka.snipmeandroid.domain.snippets.SnippetLanguage
12+
import pl.tkadziolka.snipmeandroid.domain.snippets.*
1613
import pl.tkadziolka.snipmeandroid.ui.main.*
1714
import pl.tkadziolka.snipmeandroid.util.view.SnippetFilter
1815
import java.util.*
@@ -91,6 +88,7 @@ class MainModelPlugin : ModelPlugin<Bridge.MainModelBridge>(), Bridge.MainModelB
9188
userReaction = it.userReaction.toModelUserReaction()
9289
isLiked = it.userReaction.toModelReactionState(UserReaction.LIKE)
9390
isDisliked = it.userReaction.toModelReactionState(UserReaction.DISLIKE)
91+
isSaved = calculateSavedState(it.isOwner, it.visibility)
9492
timeAgo = DateUtils.getRelativeTimeSpanString(
9593
it.modifiedAt.time,
9694
Date().time,
@@ -131,12 +129,21 @@ class MainModelPlugin : ModelPlugin<Bridge.MainModelBridge>(), Bridge.MainModelB
131129
}
132130

133131
private fun UserReaction.toModelUserReaction(): Bridge.UserReaction =
134-
when(this) {
132+
when (this) {
135133
UserReaction.LIKE -> Bridge.UserReaction.LIKE
136134
UserReaction.DISLIKE -> Bridge.UserReaction.DISLIKE
137135
else -> Bridge.UserReaction.NONE
138136
}
139137

140138
private fun UserReaction.toModelReactionState(reaction: UserReaction) =
141139
if (this == UserReaction.NONE) null else this == reaction
140+
141+
private fun calculateSavedState(
142+
isOwner: Boolean,
143+
visibility: SnippetVisibility
144+
): Boolean? = when {
145+
isOwner && visibility == SnippetVisibility.PUBLIC -> false
146+
isOwner && visibility == SnippetVisibility.PRIVATE -> true
147+
else -> null
148+
}
142149
}
Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
11
import 'package:flutter/cupertino.dart';
22
import 'package:flutter/foundation.dart';
3+
import 'package:flutter_module/model/main_model.dart';
34
import 'package:flutter_module/presentation/navigation/screen_navigator.dart';
45
import 'package:flutter_module/presentation/screens/details_screen.dart';
56
import 'package:flutter_module/utils/extensions/text_extensions.dart';
67
import 'package:go_router/go_router.dart';
78

89
class DetailsNavigator extends ScreenNavigator {
9-
String? _snippetId;
10+
Snippet? _snippet;
1011

11-
String? get snippetId => _snippetId;
12+
Snippet? get snippet => _snippet;
1213

13-
void goToDetails(BuildContext context, String snippetId) {
14-
_snippetId = snippetId;
14+
void goToDetails(BuildContext context, Snippet snippet) {
15+
_snippet = snippet;
1516
router.push(DetailsScreen.name.route);
1617
}
1718
}

flutter_module/lib/presentation/screens/details_screen.dart

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import 'package:flutter/material.dart';
22
import 'package:flutter_hooks/flutter_hooks.dart';
3+
import 'package:flutter_module/model/main_model.dart';
34
import 'package:flutter_module/presentation/navigation/details/details_navigator.dart';
45
import 'package:flutter_module/presentation/screens/named_screen.dart';
6+
import 'package:flutter_module/presentation/widgets/snippet_action_bar.dart';
57
import 'package:flutter_module/utils/hooks/use_navigator.dart';
68
import 'package:go_router/go_router.dart';
79

@@ -14,28 +16,38 @@ class DetailsScreen extends NamedScreen {
1416

1517
@override
1618
Widget builder(BuildContext context, GoRouterState state) {
17-
return _DetailsPage(navigator: navigator);
19+
return _DetailsPage(navigator: navigator, snippet: navigator.snippet);
1820
}
1921
}
2022

2123
class _DetailsPage extends HookWidget {
2224
const _DetailsPage({
2325
Key? key,
2426
required this.navigator,
27+
required this.snippet,
2528
}) : super(key: key);
2629

2730
final DetailsNavigator navigator;
31+
final Snippet? snippet;
2832

2933
@override
3034
Widget build(BuildContext context) {
3135
useNavigator([navigator]);
3236

37+
// TODO Add view state wrapper and show error for null snippet
3338
return Scaffold(
3439
appBar: AppBar(
3540
leading: BackButton(onPressed: navigator.back),
3641
),
3742
body: Center(
38-
child: Text(DetailsScreen.name),
43+
child: SnippetActionBar(
44+
snippet: snippet!,
45+
onLikeTap: () {},
46+
onDislikeTap: () {},
47+
onSaveTap: () {},
48+
onCopyTap: () {},
49+
onShareTap: () {},
50+
),
3951
),
4052
);
4153
}

flutter_module/lib/presentation/screens/main_screen.dart

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import 'package:flutter_module/presentation/widgets/snippet_list_item.dart';
1010
import 'package:flutter_module/presentation/widgets/view_state_wrapper.dart';
1111
import 'package:flutter_module/utils/hooks/use_navigator.dart';
1212
import 'package:flutter_module/utils/hooks/use_observable_state_hook.dart';
13+
import 'package:flutter_module/utils/mock/mocks.dart';
1314
import 'package:go_router/go_router.dart';
1415
import 'package:go_router/src/state.dart';
1516
import 'package:go_router_plus/go_router_plus.dart';
@@ -91,7 +92,7 @@ class _MainPage extends HookWidget {
9192
},
9293
),
9394
floatingActionButton: FloatingActionButton(
94-
onPressed: () => model.loadNextPage(),
95+
onPressed: () => detailsNavigator.goToDetails(context, Mocks.snippet),
9596
tooltip: 'Increment',
9697
child: const Icon(Icons.add),
9798
),
@@ -132,7 +133,7 @@ class _MainPageData extends StatelessWidget {
132133
child: SnippetListTile(
133134
snippet: snippet,
134135
onTap: () {
135-
navigator.goToDetails(context, snippet.uuid!);
136+
navigator.goToDetails(context, snippet);
136137
},
137138
),
138139
);

flutter_module/lib/presentation/widgets/snippet_action_bar.dart

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,60 @@
11
import 'package:flutter/material.dart';
22
import 'package:flutter/widgets.dart';
33
import 'package:flutter_module/model/main_model.dart';
4+
import 'package:flutter_module/presentation/styles/dimens.dart';
45
import 'package:flutter_module/presentation/styles/surface_styles.dart';
56
import 'package:flutter_module/presentation/widgets/state_icon.dart';
67

78
class SnippetActionBar extends StatelessWidget {
89
const SnippetActionBar({
910
Key? key,
1011
required this.snippet,
12+
this.onLikeTap,
13+
this.onDislikeTap,
14+
this.onSaveTap,
15+
this.onCopyTap,
16+
this.onShareTap,
1117
}) : super(key: key);
1218

1319
final Snippet snippet;
20+
final GestureTapCallback? onLikeTap;
21+
final GestureTapCallback? onDislikeTap;
22+
final GestureTapCallback? onSaveTap;
23+
final GestureTapCallback? onCopyTap;
24+
final GestureTapCallback? onShareTap;
1425

1526
@override
1627
Widget build(BuildContext context) {
1728
return SurfaceStyles.actionCard(
1829
child: Row(
30+
mainAxisSize: MainAxisSize.min,
1931
children: [
2032
StateIcon(
2133
icon: Icons.thumb_up_alt_outlined,
2234
active: snippet.isLiked,
35+
onTap: snippet.isLiked == false ? null : onLikeTap,
2336
),
37+
const SizedBox(width: Dimens.l),
2438
StateIcon(
2539
icon: Icons.thumb_down_alt_outlined,
2640
active: snippet.isDisliked,
41+
onTap: snippet.isDisliked == false ? null : onDislikeTap,
2742
),
43+
const SizedBox(width: Dimens.l),
2844
StateIcon(
2945
icon: Icons.save_alt_outlined,
3046
active: snippet.isSaved,
47+
onTap: snippet.isSaved == false ? null : onSaveTap,
3148
),
32-
const StateIcon(
49+
const SizedBox(width: Dimens.l),
50+
StateIcon(
3351
icon: Icons.copy_all_outlined,
52+
onTap: onCopyTap,
3453
),
35-
const StateIcon(
54+
const SizedBox(width: Dimens.l),
55+
StateIcon(
3656
icon: Icons.share,
57+
onTap: onShareTap,
3758
),
3859
],
3960
),

flutter_module/lib/presentation/widgets/state_icon.dart

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,33 @@
1-
import 'dart:ui';
2-
31
import 'package:flutter/material.dart';
42
import 'package:flutter_module/presentation/styles/color_styles.dart';
3+
import 'package:flutter_module/presentation/styles/dimens.dart';
54

65
class StateIcon extends StatelessWidget {
76
const StateIcon({
87
Key? key,
98
required this.icon,
109
this.active,
10+
this.onTap,
1111
}) : super(key: key);
1212

1313
final IconData icon;
1414
final bool? active;
15+
final GestureTapCallback? onTap;
1516

1617
@override
1718
Widget build(BuildContext context) {
1819
final color = getColorByState(active);
19-
return Icon(icon, color: color);
20+
return SizedBox(
21+
width: 24,
22+
height: 24,
23+
child: IconButton(
24+
padding: EdgeInsets.zero,
25+
splashRadius: Dimens.xl,
26+
icon: Icon(icon),
27+
color: color,
28+
onPressed: onTap,
29+
),
30+
);
2031
}
2132

2233
Color getColorByState(bool? active) {

flutter_module/lib/utils/mock/mocks.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ class Mocks {
88
owner: Owner(id: 0, login: 'Snippet owner'),
99
timeAgo: '2 days ago',
1010
voteResult: 32,
11+
isLiked: true,
12+
isDisliked: false,
1113
language: SnippetLanguage(
1214
raw: 'Kotlin',
1315
type: SnippetLanguageType.kotlin,

0 commit comments

Comments
 (0)