Skip to content

Commit

Permalink
feat: 컨텐츠 상세 수정 (#50)
Browse files Browse the repository at this point in the history
* feat: 해시태그뷰 api 타입수정 및 페이지네이션
  • Loading branch information
nain93 authored Aug 3, 2023
1 parent 6fa27d5 commit 9ea2d05
Show file tree
Hide file tree
Showing 25 changed files with 797 additions and 325 deletions.
1 change: 1 addition & 0 deletions lib/constants/color_constants.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class AppColors {
static const Color subTitle = Color(0xFF818181);
static const Color grayBackground = Color(0xFFD9D9D9);
static const Color hashtagBackground = Color(0xFFF8F8F8);
static const Color contentHashtagBackground = Color(0xFFFFF3EE);

///font color
static const Color fontTitleColor = Color(0xff000000);
Expand Down
43 changes: 43 additions & 0 deletions lib/providers/content_detail_provider.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import 'dart:async';

import 'package:moa_app/models/content_model.dart';
import 'package:moa_app/repositories/content_repository.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';

part 'content_detail_provider.g.dart';

@riverpod
class ContentDetail extends _$ContentDetail {
Future<ContentModel> fetchItem({required String contentId}) async {
// get the [KeepAliveLink]
var link = ref.keepAlive();
// a timer to be used by the callbacks below
Timer? timer;
// An object from package:dio that allows cancelling http requests
// When the provider is destroyed, cancel the http request and the timer
ref.onDispose(() {
timer?.cancel();
});
// When the last listener is removed, start a timer to dispose the cached data
ref.onCancel(() {
// start a 30 second timer
timer = Timer(const Duration(seconds: 30), () {
// dispose on timeout
link.close();
});
});
// If the provider is listened again after it was paused, cancel the timer
ref.onResume(() {
timer?.cancel();
});

var data =
await ContentRepository.instance.getContentDetail(contentId: contentId);
return data;
}

@override
Future<ContentModel?> build() async {
return null;
}
}
43 changes: 43 additions & 0 deletions lib/providers/folder_detail_provider.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import 'dart:async';

import 'package:moa_app/models/content_model.dart';
import 'package:moa_app/repositories/folder_repository.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';

part 'folder_detail_provider.g.dart';

/// AsyncNotifierProvider
// @Riverpod(keepAlive: true)
@riverpod
class FolderDetail extends _$FolderDetail {
Future<List<ContentModel>> fetchItem({required String folderName}) async {
// get the [KeepAliveLink]
var link = ref.keepAlive();
// a timer to be used by the callbacks below
Timer? timer;
// An object from package:dio that allows cancelling http requests
// When the provider is destroyed, cancel the http request and the timer
ref.onDispose(() {
timer?.cancel();
});
// When the last listener is removed, start a timer to dispose the cached data
ref.onCancel(() {
// start a 30 second timer
timer = Timer(const Duration(seconds: 30), () {
// dispose on timeout
link.close();
});
});
// If the provider is listened again after it was paused, cancel the timer
ref.onResume(() {
timer?.cancel();
});

var data =
FolderRepository.instance.getFolderDetailList(folderName: folderName);
return data;
}

@override
Future<void> build() async {}
}
62 changes: 61 additions & 1 deletion lib/providers/folder_view_provider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,72 @@ class FolderView extends _$FolderView {
timer?.cancel();
});

var data = FolderRepository.instance.getFolderList();
var data = await FolderRepository.instance.getFolderList();
return data;
}

@override
Future<List<FolderModel>> build() async {
return fetchItem();
}

Future<void> addFolder({
required String folderName,
}) async {
state = const AsyncValue.loading();

state = await AsyncValue.guard(() async {
// await FolderRepository.instance.addFolder(folderName: folderName);
return fetchItem();
// return [
// ...state.value ?? [],
// FolderModel(
// folderId: 0,
// folderName: folderName,
// count: 0,
// )
// ];
});
}

Future<void> editFolderName({
required String currentFolderName,
required String editFolderName,
}) async {
state = const AsyncValue.loading();

state = await AsyncValue.guard(() async {
// await FolderRepository.instance.editFolderName(
// currentFolderName: currentFolderName,
// editFolderName: editFolderName,
// );
return fetchItem();

// return state.value?.map((element) {
// if (element.folderName == currentFolderName) {
// return FolderModel(
// folderId: element.folderId,
// folderName: editFolderName,
// count: element.count,
// );
// }
// return element;
// }).toList() ??
// [];
});
}

Future<void> deleteFolder({required String folderName}) async {
state = const AsyncValue.loading();

state = await AsyncValue.guard(() async {
// await FolderRepository.instance.deleteFolder(folderName: folderName);

return fetchItem();
// return state.value
// ?.where((element) => element.folderName != folderName)
// .toList() ??
// [];
});
}
}
61 changes: 40 additions & 21 deletions lib/providers/hashtag_view_provider.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'dart:async';

import 'package:moa_app/models/content_model.dart';
import 'package:moa_app/repositories/content_repository.dart';
import 'package:moa_app/repositories/hashtag_repository.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';

Expand All @@ -11,27 +12,27 @@ part 'hashtag_view_provider.g.dart';
@riverpod
class HashtagView extends _$HashtagView {
Future<(List<ContentModel>, int)> fetchItem() async {
// get the [KeepAliveLink]
var link = ref.keepAlive();
// a timer to be used by the callbacks below
Timer? timer;
// An object from package:dio that allows cancelling http requests
// When the provider is destroyed, cancel the http request and the timer
ref.onDispose(() {
timer?.cancel();
});
// When the last listener is removed, start a timer to dispose the cached data
ref.onCancel(() {
// start a 30 second timer
timer = Timer(const Duration(seconds: 30), () {
// dispose on timeout
link.close();
});
});
// If the provider is listened again after it was paused, cancel the timer
ref.onResume(() {
timer?.cancel();
});
// // get the [KeepAliveLink]
// var link = ref.keepAlive();
// // a timer to be used by the callbacks below
// Timer? timer;
// // An object from package:dio that allows cancelling http requests
// // When the provider is destroyed, cancel the http request and the timer
// ref.onDispose(() {
// timer?.cancel();
// });
// // When the last listener is removed, start a timer to dispose the cached data
// ref.onCancel(() {
// // start a 30 second timer
// timer = Timer(const Duration(seconds: 30), () {
// // dispose on timeout
// link.close();
// });
// });
// // If the provider is listened again after it was paused, cancel the timer
// ref.onResume(() {
// timer?.cancel();
// });

var data = await HashtagRepository.instance.getHashtagView();
return data;
Expand All @@ -42,6 +43,24 @@ class HashtagView extends _$HashtagView {
return fetchItem();
}

Future<void> deleteContent({required String contentId, required}) async {
state = const AsyncValue.loading();

state = await AsyncValue.guard(() async {
await ContentRepository.instance.deleteContent(contentId: contentId);
var value = state.value;
if (value != null) {
var (list, count) = value;
var filteredList =
list.where((element) => element.contentId != contentId).toList();

return (filteredList, count);
}

return value!;
});
}

Future<(List<ContentModel>, int)> loadMoreData({
int? page,
int? size,
Expand Down
64 changes: 52 additions & 12 deletions lib/repositories/content_repository.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,16 @@ abstract class IContentRepository {
Future<ContentModel> getContentDetail({
required String contentId,
});

Future<void> editContent({
required String contentId,
required ContentModel content,
required String hashTagStringList,
});

Future<void> deleteContent({
required String contentId,
});
}

class ContentRepository implements IContentRepository {
Expand Down Expand Up @@ -77,23 +87,53 @@ class ContentRepository implements IContentRepository {
Future<ContentModel> getContentDetail({required String contentId}) async {
var token = await TokenRepository.instance.getToken();

var res = await dio.get(
'/api/v1/content/detail/view?contentId=$contentId',
try {
var res = await dio.get(
'/api/v1/content/detail/view?contentId=$contentId',
options: Options(
headers: {
'Authorization': 'Bearer $token',
},
),
);

/// 백엔드 ContentModel 타입이 통일되지 않았으므로 임시로 타입 변환해서 넣어줌
return ContentModel.fromJson({
'contentId': '0',
'contentImageUrl': res.data['data']['thumbnail_image_url'],
'contentUrl': res.data['data']['contentUrl'] ?? '',
'contentMemo': res.data['data']['memo'],
'contentName': res.data['data']['contentName'],
'contentHashTag': res.data['data']['hashTags'],
});
} catch (e) {
rethrow;
}
}

@override
Future<void> editContent({
required String contentId,
required ContentModel content,
required String hashTagStringList,
}) async {
throw UnimplementedError();
}

@override
Future<void> deleteContent({required String contentId}) async {
var token = await TokenRepository.instance.getToken();

await dio.post(
'/api/v1/content/delete',
data: {
'ids': [contentId]
},
options: Options(
headers: {
'Authorization': 'Bearer $token',
},
),
);

/// 백엔드 ContentModel 타입이 통일되지 않았으므로 임시로 타입 변환해서 넣어줌
return ContentModel.fromJson({
'contentId': '0',
'contentImageUrl': res.data['data']['thumbnail_image_url'],
'contentUrl': res.data['data']['contentUrl'] ?? '',
'contentMemo': res.data['data']['memo'],
'contentName': res.data['data']['contentName'],
'contentHashTag': res.data['data']['hashTags'],
});
}
}
Loading

0 comments on commit 9ea2d05

Please sign in to comment.