Skip to content

Commit

Permalink
## 0.8.0
Browse files Browse the repository at this point in the history
### Feature

- Add HashTag Page
  • Loading branch information
ChenDoXiu committed Dec 22, 2024
1 parent 623c28a commit 552a976
Show file tree
Hide file tree
Showing 16 changed files with 389 additions and 89 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## 0.8.0

### Feature

- Add HashTag Page

## 0.7.4

### Chore
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,11 @@ Currently implemented features:
- Clip
- Misskey Announcements
- Explore
- HashTag Page
-

Temporarily unimplemented features

- HashTag Page
- User Profile Edit
- Misskey Settings
- Antennas, Channels, Lists
Expand Down
2 changes: 1 addition & 1 deletion README.zh_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ MoeKey希望成为一个UI风格与原版Misskey保持一致。功能完善的Mi
- 便签
- 系统公告
- 发现
- HashTag 浏览

暂时未实现的功能

- HashTag 浏览
- 个人资料编辑
- Misskey设置
- 天线,频道,列表
Expand Down
18 changes: 18 additions & 0 deletions lib/apis/services/notes_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -171,4 +171,22 @@ class NotesService extends MisskeyApiServices {
}
return List<NoteModel>.from(data.map((e) => NoteModel.fromMap(e)));
}

Future<List<NoteModel>> searchByTag({
required String tag,
String? sinceId,
String? untilId,
int limit = 10,
}) async {
var data = await client.post("/notes/search-by-tag", data: {
"tag": tag,
"limit": limit,
if (sinceId != null) "sinceId": sinceId,
if (untilId != null) "untilId": untilId,
});
if (data == null) {
return [];
}
return List<NoteModel>.from(data.map((e) => NoteModel.fromMap(e)));
}
}
32 changes: 32 additions & 0 deletions lib/hook/use_mk_refresh_load_list_controller.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import 'package:flutter/widgets.dart';
import 'package:flutter_hooks/flutter_hooks.dart';

import '../widgets/mk_refresh_load.dart';

MkRefreshLoadListController useMkRefreshLoadListController() {
return use(_MkRefreshLoadListControllerHook());
}

class _MkRefreshLoadListControllerHook
extends Hook<MkRefreshLoadListController> {
@override
HookState<MkRefreshLoadListController, Hook<MkRefreshLoadListController>>
createState() {
return _MkRefreshLoadListControllerHookState();
}
}

class _MkRefreshLoadListControllerHookState extends HookState<
MkRefreshLoadListController, _MkRefreshLoadListControllerHook> {
late final controller = MkRefreshLoadListController();

@override
MkRefreshLoadListController build(BuildContext context) {
return controller;
}

@override
void dispose() {
controller.dispose();
}
}
86 changes: 86 additions & 0 deletions lib/pages/hashtag/hashtag_page.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:moekey/apis/models/note.dart';
import 'package:moekey/hook/use_mk_refresh_load_list_controller.dart';
import 'package:moekey/widgets/mk_header.dart';
import 'package:moekey/widgets/mk_scaffold.dart';
import 'package:moekey/widgets/notes/note_pagination_list.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';

import '../../status/misskey_api.dart';

part 'hashtag_page.g.dart';

class HashtagPage extends HookConsumerWidget {
const HashtagPage({super.key, required this.name});

final String name;

@override
Widget build(BuildContext context, WidgetRef ref) {
var model = hashTagPageProvider(name);
var state = ref.watch(model);
var data = state.valueOrNull;
var controller = useMkRefreshLoadListController();
return MkScaffold(
header: MkAppbar(
showBack: true,
content: GestureDetector(
onTap: () {
controller.refresh();
},
child: Text(
"#$name",
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
),
),
body: Center(
child: MkPaginationNoteList(
onLoad: () => ref.read(model.notifier).load(),
onRefresh: () => ref.refresh(model.future),
hasMore: data?.hasMore ?? true,
items: data?.list,
controller: controller,
),
),
);
}
}

@riverpod
class HashTagPage extends _$HashTagPage {
@override
FutureOr<NoteListModel> build(String tag) async {
var model = NoteListModel();
model.list = await notes();
return model;
}

Future<List<NoteModel>> notes({String? untilId}) async {
var apis = ref.read(misskeyApisProvider);
var list = await apis.notes.searchByTag(tag: tag, untilId: untilId);
return list;
}

load() async {
if (state.isLoading) return;
state = const AsyncValue.loading();
var model = state.valueOrNull ?? NoteListModel();
try {
String? untilId;
if (state.valueOrNull?.list.isNotEmpty ?? false) {
untilId = state.valueOrNull?.list.last.id;
}
List<NoteModel> notesList = await notes(untilId: untilId);

model.list += notesList;
if (notesList.isEmpty) {
model.hasMore = false;
}
} finally {
state = AsyncData(model);
}
}
}
14 changes: 7 additions & 7 deletions lib/pages/home/home_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -96,12 +96,12 @@ class HomePage extends HookConsumerWidget {
onSelect: _closeDrawer,
)
: null,
endDrawer: constraints.maxWidth < 500
? Container(
color: themes.panelColor,
child: const WidgetsListPage(),
)
: null,
// endDrawer: constraints.maxWidth < 500
// ? Container(
// color: themes.panelColor,
// child: const WidgetsListPage(),
// )
// : null,
body: Stack(
children: [
Row(
Expand All @@ -125,7 +125,7 @@ class HomePage extends HookConsumerWidget {
child: child,
),
),
if (constraints.maxWidth >= 1090) const WidgetsListPage()
// if (constraints.maxWidth >= 1090) const WidgetsListPage()
],
),
if (constraints.maxWidth < 500)
Expand Down
1 change: 0 additions & 1 deletion lib/pages/home/home_page_state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ class HomeState {
"icon": TablerIcons.bell,
"label": S.current.notifications,
"id": "notifications",
"key": GlobalKey<MkTabBarRefreshScrollState>(),
"onTop": ({Key? key}) => {
(key as GlobalKey<MkTabBarRefreshScrollState>)
.currentState
Expand Down
71 changes: 62 additions & 9 deletions lib/pages/users/user_overview.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import '../../widgets/loading_weight.dart';
import '../../widgets/mk_card.dart';
import '../../widgets/mk_image.dart';
import '../../widgets/mk_parallax.dart';
import '../../widgets/notes/note_card.dart';

class UserOverview extends HookConsumerWidget {
const UserOverview({
Expand All @@ -31,8 +32,17 @@ class UserOverview extends HookConsumerWidget {

@override
Widget build(BuildContext context, WidgetRef ref) {
var dataProvider = userNotesListProvider(userId: userId);

var dataProvider = userNotesListProvider(
userId: userId,
withChannelNotes: true,
withFiles: false,
withRenotes: true,
withReplies: true,
);
var userProvider = userInfoProvider(userId: userId);
var user = ref.watch(userProvider);
var userPinNote = user.valueOrNull?.pinnedNotes ?? [];
var themes = ref.watch(themeColorsProvider);
var data = ref.watch(dataProvider);
return MkPaginationNoteList(
onLoad: () => ref.read(dataProvider.notifier).load(),
Expand All @@ -43,10 +53,52 @@ class UserOverview extends HookConsumerWidget {
padding: const EdgeInsets.only(bottom: 8.0),
child: UserHomeCard(userId: userId),
),
)
),
SliverList.separated(
itemBuilder: (BuildContext context, int index) {
BorderRadius borderRadius = const BorderRadius.all(Radius.zero);
if (index == 0) {
borderRadius = borderRadius.copyWith(
topLeft: Radius.circular(12),
topRight: Radius.circular(12),
);
}
if (index + 1 == userPinNote.length) {
borderRadius = borderRadius.copyWith(
bottomLeft: Radius.circular(12),
bottomRight: Radius.circular(12),
);
}

return RepaintBoundary(
child: NoteCard(
key: ValueKey(userPinNote[index].id),
borderRadius: borderRadius,
pined: true,
data: userPinNote[index]),
);
},
separatorBuilder: (BuildContext context, int index) {
return SizedBox(
width: double.infinity,
height: 1,
child: DecoratedBox(
decoration: BoxDecoration(
color: themes.dividerColor,
),
),
);
},
itemCount: userPinNote.length,
),
SliverToBoxAdapter(
child: Padding(
padding: const EdgeInsets.only(bottom: 8.0),
),
),
],
hasMore: data.valueOrNull?.hasMore ?? true,
items: data.valueOrNull?.list ?? [],
items: data.valueOrNull?.list,
);
}
}
Expand Down Expand Up @@ -702,18 +754,19 @@ class _UserBanner extends StatelessWidget {
label: S.current.openInNewTab,
icon: TablerIcons.external_link,
onTap: () {
launchUrlString(
"https://${userData.host}/@${userData.username}");
var url = userData.url ??
"https://${userData.host}/@${userData.username}";
launchUrlString(url);
return false;
},
),
ContextMenuItem(
label: S.current.copyUserHomeLink,
icon: TablerIcons.home,
onTap: () {
Clipboard.setData(ClipboardData(
text:
"https://${userData.host}/@${userData.username}"));
var url = userData.url ??
"https://${userData.host}/@${userData.username}";
Clipboard.setData(ClipboardData(text: url));
return false;
},
),
Expand Down
4 changes: 4 additions & 0 deletions lib/router/router.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'package:flutter/cupertino.dart';
import 'package:go_router/go_router.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:moekey/logger.dart';
import 'package:moekey/pages/hashtag/hashtag_page.dart';
import 'package:moekey/pages/login/login_page.dart';
import 'package:moekey/pages/notes/note_page.dart';
import 'package:moekey/pages/notifications/notifications_page.dart';
Expand Down Expand Up @@ -164,6 +165,9 @@ GoRouter router(Ref ref) {
username: status.pathParameters['username']!,
),
),
GoRoute(path: "/tags/:name", builder: (_, status) => HashtagPage(
name: status.pathParameters['name']!,
)),
],
),
GoRoute(
Expand Down
Loading

0 comments on commit 552a976

Please sign in to comment.