Skip to content

Commit

Permalink
Merge pull request #212 from sparcs-kaist/feat/caching-for-post-write…
Browse files Browse the repository at this point in the history
…-page

[Feature] caching for post write page
  • Loading branch information
thomaskim1130 authored Aug 29, 2024
2 parents 3df2fc3 + 641264f commit 5110cae
Show file tree
Hide file tree
Showing 6 changed files with 170 additions and 18 deletions.
3 changes: 2 additions & 1 deletion assets/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,8 @@
"confirm": "OK",
"noBlockedUsers": "There are no blocked users.",
"noNickname": "No nickname",
"exitConfirm": "Do you really want to go back? Your post will not be saved"
"exitConfirm": "Do you really want to go back? Your post will not be saved",
"tempSave" : "Save in drafts"
},
"popUpMenuButtons": {
"downloadSucceed": "File downloaded successfully",
Expand Down
3 changes: 2 additions & 1 deletion assets/translations/ko.json
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,8 @@
"confirm": "확인",
"noBlockedUsers": "차단한 유저가 없습니다.",
"noNickname": "닉네임이 없음",
"exitConfirm": "정말로 돌아가시겠습니까? 작성하신 글은 저장되지 않습니다"
"exitConfirm": "정말로 돌아가시겠습니까? 작성하신 글은 저장되지 않습니다",
"tempSave" : "임시 저장하기"
},
"popUpMenuButtons": {
"downloadSucceed": "파일 다운로드에 성공했습니다",
Expand Down
126 changes: 122 additions & 4 deletions lib/pages/post_write_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -176,12 +176,16 @@ class _PostWritePageState extends State<PostWritePage>

bool _isKeyboardClosed = true;

String userID = '';

final _editorScrollController = ScrollController();
@override
void initState() {
super.initState();
UserProvider userProvider = context.read<UserProvider>();

userID = userProvider.naUser!.uid;

context.read<NotificationProvider>().checkIsNotReadExist(userProvider);
debugPrint("post_write_page.dart: ${widget.previousBoard}");
if (widget.previousArticle != null) {
Expand Down Expand Up @@ -263,7 +267,38 @@ class _PostWritePageState extends State<PostWritePage>
/// 이전 게시물의 데이터를 가져온다.
Future<void> _initPostWritePost() async {
await _getBoardList();
await _getPostContent();
await _getCachedContents();
}

Future<void> cacheCurrentData() async {
var data = {
'title': _titleController.text,
'content':
DeltaToHTML.encodeJson(_quillController.document.toDelta().toJson()),
'is_content_sexual': _selectedCheckboxes[1],
'is_content_social': _selectedCheckboxes[2],
'name_type': (_chosenBoardValue != null)
? (_defaultBoardDetailActionModel.slug == 'with-school'
? 'REALNAME'
: _chosenBoardValue!.slug == "talk" &&
_selectedCheckboxes[0]! == true
? 'ANONYMOUS'
: 'REGULAR')
: 'REGULAR',
'parent_topic' : _chosenTopicValue!.id == -1 ? '' : _chosenTopicValue!.slug,
'parent_board' : _chosenBoardValue!.id == -1 ? '' : _chosenBoardValue!.slug,
'attachments' : _chosenBoardValue!.id == -1 ? '' : _chosenBoardValue!.slug,
};

data['attachments'] = _attachmentList;

String key = _isEditingPost
? '/cache/${widget.previousArticle!.id}/'
: '/cache/${userID}/';

await cacheApiData(key, data);
debugPrint(key);
debugPrint(data as String?);
}

/// 사용자가 선택 가능한 게시판 목록을 가져오는 함수.
Expand Down Expand Up @@ -326,6 +361,66 @@ class _PostWritePageState extends State<PostWritePage>
}
}

Future<void> _getCachedContents() async {
String key = (_isEditingPost)
? '/cache/${widget.previousArticle!.id}/'
: '/cache/${userID}/';
Map<String, dynamic>? cachedData = await fetchCachedApiData(key);
debugPrint('cache : ${cachedData}');
if (cachedData == null && _isEditingPost) {
await _getPostContent();
return;
}

if (cachedData == null) {
return;
}

String? title = cachedData['title'];
_titleController.text = title ?? '';

for (int i = 0; i < cachedData['attachments'].length; i++) {
AttachmentModel attachment = cachedData['attachments'][i];
int id = attachment.id;
String? fileUrlPath = attachment.file;
String fileUrlName = _extractAndDecodeFileNameFromUrl(attachment.file);
int? fileUrlSize = attachment.size ?? 0;

// TODO: fileType이 이미지인지 아닌지 판단해서 넣기.
_attachmentList.add(AttachmentsFormat(
fileType: FileType.image,
isNewFile: false,
id: id,
fileUrlPath: fileUrlPath,
fileUrlName: fileUrlName,
fileUrlSize: fileUrlSize));
}

setState(() {
_quillController.document = (cachedData['content'] != null)
? quill.Document.fromDelta(_htmlToQuillDelta(cachedData['content']))
: '';
_isFileMenuBarSelected = _attachmentList.isNotEmpty;

//TODO: 명명 규칙 다름
_selectedCheckboxes[0] = cachedData['name_type'] == 2 ? true : false;
_selectedCheckboxes[1] = cachedData['is_content_sexual'] ?? false;
_selectedCheckboxes[2] = cachedData['is_content_social'] ?? false;
_isLoading = false;
});

setState(() {
BoardDetailActionModel boardDetailActionModel =
_findBoardListValue(cachedData['parent_board']);
_specTopicList = [_defaultTopicModelNone];
_specTopicList.addAll(boardDetailActionModel.topics);
_chosenTopicValue = (cachedData['parent_topic'] == null)
? _specTopicList[0]
: _findSpecTopicListValue(cachedData['parent_topic'].toString());
_chosenBoardValue = boardDetailActionModel;
});
}

/// 기존 게시물의 내용과 첨부 파일 가져오기.
Future<void> _getPostContent() async {
// 새로 작성하는 게시물의 경우 함수 종료.
Expand Down Expand Up @@ -436,8 +531,17 @@ class _PostWritePageState extends State<PostWritePage>
builder: (context) => ExitConfirmDialog(
userProvider: userProvider,
targetContext: context,
onTap: () {
Navigator.pop(context, true); //dialog pop
onTapConfirm: () async {
//dialog pop
String key = _isEditingPost
? '/cache/${widget.previousArticle!.id}/'
: '/cache/${userID}';
await cacheApiData(key, null);
Navigator.pop(context, true);
},
onTapSave: () async {
await cacheCurrentData();
Navigator.pop(context, true);
},
));
return shouldPop ?? false;
Expand Down Expand Up @@ -497,9 +601,23 @@ class _PostWritePageState extends State<PostWritePage>
builder: (context) => ExitConfirmDialog(
userProvider: userProvider,
targetContext: context,
onTap: () {
onTapConfirm: () async {
// 사용자가 미리 뒤로가기 버튼을 누르는 경우 에러 방지를 위해
// try-catch 문을 도입함.
String key = _isEditingPost
? '/cache/${widget.previousArticle!.id}/'
: '/cache/${userID}';
await cacheApiData(key, null);
try {
Navigator.of(context)
..pop() //dialog pop
..pop(); //PostWritePage pop
} catch (error) {
debugPrint("pop error: $error");
}
},
onTapSave: () async {
await cacheCurrentData();
try {
Navigator.of(context)
..pop() //dialog pop
Expand Down
6 changes: 4 additions & 2 deletions lib/translations/codegen_loader.g.dart
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,8 @@ class CodegenLoader extends AssetLoader{
"confirm": "OK",
"noBlockedUsers": "There are no blocked users.",
"noNickname": "No nickname",
"exitConfirm": "Do you really want to go back? Your post will not be saved"
"exitConfirm": "Do you really want to go back? Your post will not be saved",
"tempSave": "Save in drafts"
},
"popUpMenuButtons": {
"downloadSucceed": "File downloaded successfully",
Expand Down Expand Up @@ -361,7 +362,8 @@ static const Map<String,dynamic> ko = {
"confirm": "확인",
"noBlockedUsers": "차단한 유저가 없습니다.",
"noNickname": "닉네임이 없음",
"exitConfirm": "정말로 돌아가시겠습니까? 작성하신 글은 저장되지 않습니다"
"exitConfirm": "정말로 돌아가시겠습니까? 작성하신 글은 저장되지 않습니다",
"tempSave": "임시 저장하기"
},
"popUpMenuButtons": {
"downloadSucceed": "파일 다운로드에 성공했습니다",
Expand Down
1 change: 1 addition & 0 deletions lib/translations/locale_keys.g.dart
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ abstract class LocaleKeys {
static const dialogs_noBlockedUsers = 'dialogs.noBlockedUsers';
static const dialogs_noNickname = 'dialogs.noNickname';
static const dialogs_exitConfirm = 'dialogs.exitConfirm';
static const dialogs_tempSave = 'dialogs.tempSave';
static const dialogs = 'dialogs';
static const popUpMenuButtons_downloadSucceed = 'popUpMenuButtons.downloadSucceed';
static const popUpMenuButtons_downloadFailed = 'popUpMenuButtons.downloadFailed';
Expand Down
49 changes: 39 additions & 10 deletions lib/widgets/dialogs.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1101,14 +1101,17 @@ class ExitConfirmDialog extends StatelessWidget {
final BuildContext targetContext;

/// '확인' 버튼을 눌렀을 때 적용되는 onTap 메서드
final void Function()? onTap;
final void Function()? onTapConfirm;

const ExitConfirmDialog({
super.key,
required this.userProvider,
required this.targetContext,
required this.onTap,
});
/// '임시 저장' 버튼을 눌렀을 때 적용되는 onTap 메서드
final void Function()? onTapSave;

const ExitConfirmDialog(
{super.key,
required this.userProvider,
required this.targetContext,
required this.onTapConfirm,
required this.onTapSave});

@override
Widget build(BuildContext context) {
Expand Down Expand Up @@ -1150,7 +1153,7 @@ class ExitConfirmDialog extends StatelessWidget {
children: [
InkWell(
onTap: () {
// PostWritePage에서 pop해야 하므로
// 이전 페이지(ex:PostWritePage)에서 pop해야 하므로
// targetContext 사용.
Navigator.pop(targetContext, false);
},
Expand Down Expand Up @@ -1179,8 +1182,34 @@ class ExitConfirmDialog extends StatelessWidget {
),
const SizedBox(width: 10),
InkWell(
// 인자로 전달받은 onTap 사용.
onTap: onTap,
// 글 제목 / 내용 임시 저장하기 구현
onTap: () {
onTapSave!();
//onTapConfirm!();
},
child: Container(
decoration: const BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(20)),
color: Colors.grey //ColorsInfo.newaraSoft,
),
width: 120,
height: 40,
child: Center(
child: Text(
LocaleKeys.dialogs_tempSave.tr(),
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
color: Colors.white,
),
),
),
),
),
const SizedBox(width: 10),
InkWell(
// 나가기(확인) 구현
onTap: onTapConfirm,
child: Container(
decoration: const BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(20)),
Expand Down

0 comments on commit 5110cae

Please sign in to comment.