From ca166ab0e96a828fd2ec3ceef81693ff215e1f6f Mon Sep 17 00:00:00 2001 From: liujiajun Date: Tue, 23 Apr 2024 20:26:46 +0800 Subject: [PATCH] =?UTF-8?q?mynews=20=E6=90=9C=E7=B4=A2=E9=A1=B5=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E6=90=9C=E7=B4=A2=E5=8E=86=E5=8F=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: liujiajun --- .../entry/src/main/ets/pages/SearchPage.ets | 18 +- .../main/ets/view/Search/SearchHistory.ets | 229 ++++++++++++++++++ .../entry/src/main/ets/view/Search/TopBar.ets | 13 +- .../main/ets/view/Search/TrendingTopics.ets | 9 + .../main/resources/base/element/string.json | 24 ++ .../main/resources/en_US/element/string.json | 24 ++ .../main/resources/zh_CN/element/string.json | 24 ++ 7 files changed, 336 insertions(+), 5 deletions(-) create mode 100644 scenario/MyNews/entry/src/main/ets/view/Search/SearchHistory.ets diff --git a/scenario/MyNews/entry/src/main/ets/pages/SearchPage.ets b/scenario/MyNews/entry/src/main/ets/pages/SearchPage.ets index 51f99db4..bfff84ab 100644 --- a/scenario/MyNews/entry/src/main/ets/pages/SearchPage.ets +++ b/scenario/MyNews/entry/src/main/ets/pages/SearchPage.ets @@ -20,12 +20,18 @@ import TopBar from '../view/Search/TopBar'; import BottomBar from '../view/Search/BottomBar'; import TrendingTopics from '../view/Search/TrendingTopics'; import IncognitoModeIndicator from '../view/Search/IncognitoModeIndicator'; +import SearchHistory from '../view/Search/SearchHistory' -@Entry +let para: Record = { 'search_history': [] }; +let storage: LocalStorage = new LocalStorage(para); + +@Entry(storage) @Component struct SearchPage { @State isIncognitoModeOn: boolean = false + @State searchInput: string = '' @State trendingTopicList: string[] = [] + @LocalStorageLink('search_history') searchHistoryList: string[] = [] aboutToAppear() { const params: SearchPageParams = router.getParams() as SearchPageParams @@ -42,11 +48,11 @@ struct SearchPage { build() { Column({ space: 15 }) { /* Top bar: back button + search box + search button */ - TopBar({ trendingTopic: this.trendingTopicList[0] }) + TopBar({ trendingTopic: this.trendingTopicList[0], searchInput: this.searchInput, searchHistoryList: this.searchHistoryList }) Column({ space: 15 }) { /* Trending topics */ - TrendingTopics({ trendingTopicList: this.trendingTopicList }) + TrendingTopics({ trendingTopicList: this.trendingTopicList, searchInput: this.searchInput }) Divider() .strokeWidth(1) @@ -57,7 +63,11 @@ struct SearchPage { IncognitoModeIndicator() } - /* TODO: History */ + if (this.searchHistoryList.length) { + SearchHistory({searchHistoryList: this.searchHistoryList, trendingTopicList: this.trendingTopicList, searchInput: this.searchInput}) + } + + // TODO(ljj): search result content } .width('100%') .height(0) diff --git a/scenario/MyNews/entry/src/main/ets/view/Search/SearchHistory.ets b/scenario/MyNews/entry/src/main/ets/view/Search/SearchHistory.ets new file mode 100644 index 00000000..03572e79 --- /dev/null +++ b/scenario/MyNews/entry/src/main/ets/view/Search/SearchHistory.ets @@ -0,0 +1,229 @@ +/* + * Copyright (c) 2023 Southeast University. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +// Divide the list into pairs +function groupInPairs(list: T[]): T[][] { + const pairs: T[][] = []; + + for (let i = 0; i < list.length; i += 2) { + let pair: T[] = [] + if (i + 1 === list.length) { + pair = [list[i]] + } else { + pair = [list[i], list[i + 1]]; + } + pairs.push(pair); + } + return pairs; +} + +// Dialog to delete all search history +@CustomDialog +struct DeleteAllDialog { + @Link searchHistoryList: string[] + cancel?: () => void + confirm?: () => void + controller: CustomDialogController + + build() { + Column() { + Text($r('app.string.search_deleteAll_dialogPrompt')) + .fontSize(16) + .margin({ top: 20, bottom: 10 }) + + Flex({ justifyContent: FlexAlign.SpaceBetween }) { + Button($r('app.string.search_deleteAll_dialogCancel'), { type: ButtonType.Normal }) + .width('50%') + .fontSize(15) + .backgroundColor(Color.Transparent) + .fontColor($r('app.color.light_fg_shallow')) + .border({ width: { right: 1 }, color: $r('app.color.light_border') }) + .onClick(() => { + this.controller.close() + if (this.cancel) { + this.cancel() + } + }) + Button($r('app.string.search_deleteAll_dialogConfirm')) + .width('50%') + .fontSize(15) + .backgroundColor(Color.Transparent) + .fontColor($r('app.color.primary')) + .onClick(() => { + this.controller.close() + if (this.confirm) { + this.confirm() + } + }) + }.border({ width: { top: 1 }, color: $r('app.color.light_border') }) + }.backgroundColor($r('app.color.light_bg')).borderRadius(10).width('70%') + } +} + +/** + * Search History + */ +@Component +export default struct SearchHistory { + @Link searchHistoryList: string[] + @Prop trendingTopicList: string[] + @Link searchInput: string + @State isDeleting: Boolean = false + dialogController: CustomDialogController = new CustomDialogController({ + builder: DeleteAllDialog({ + confirm: () => { + this.onDeleteAllHistory() + }, + searchHistoryList: this.searchHistoryList, + }), + alignment: DialogAlignment.Center, + cornerRadius: 10, + customStyle: true + }) + + onDeleteAllHistory() { + this.searchHistoryList = [] + } + + build() { + Column({ space: 10 }) { + Row() { + Text($r('app.string.search_searchHistory')) + .fontSize(13) + .fontColor($r('app.color.light_fg_shallow')) + if (this.isDeleting) { + Row({ space: 10 }) { + Button() { + Text($r('app.string.search_deleteAll')) + .fontSize(13) + .fontColor($r('app.color.light_fg_shallow')) + }.backgroundColor(Color.Transparent) + .onClick(() => { + this.dialogController.open() + }) + + Button() { + Text($r('app.string.search_deleteAll_finish')) + .fontSize(13) + .fontColor($r('app.color.light_fg_shallow')) + }.backgroundColor(Color.Transparent) + .onClick(() => { + this.isDeleting = false + }) + } + } else { + Button() { + Image($r('app.media.ic_public_delete')) + .size({ width: 15, height: 15 }) + .fillColor($r('app.color.light_fg_shallow')) + }.backgroundColor(Color.Transparent) + .onClick(() => { + this.isDeleting = true + }) + } + + }.width('100%').justifyContent(FlexAlign.SpaceBetween) + + ForEach(groupInPairs(this.searchHistoryList), (item: string[]) => { + Row() { + if (this.isDeleting) { + Text(item[0]) + .width('43%') + .fontSize(14) + .textOverflow({ overflow: TextOverflow.Ellipsis }) + .maxLines(1) + .onClick(() => { + this.searchInput = item[0] + // TODO(ljj): search result content + }) + Button() { + Image($r('app.media.ic_public_cancel')) + .width('10') + .fillColor($r('app.color.light_fg_shallow')) + } + .width('2%') + .backgroundColor(Color.Transparent) + .onClick(() => { + let index = this.searchHistoryList.indexOf(item[0]); + if (index !== -1) { + this.searchHistoryList.splice(index, 1) + } + }) + } else { + Text(item[0]) + .width('45%') + .fontSize(14) + .textOverflow({ overflow: TextOverflow.Ellipsis }) + .maxLines(1) + .onClick(() => { + this.searchInput = item[0] + // TODO(ljj): search result content + }) + } + + + Divider() + .width('10%') + .height(14) + .vertical(true) + .color($r('app.color.light_border')) + .strokeWidth(1) + + if (this.isDeleting) { + if (item.length > 1) { + Text(item[1]) + .width('43%') + .fontSize(14) + .textOverflow({ overflow: TextOverflow.Ellipsis }) + .maxLines(1) + .onClick(() => { + this.searchInput = item[1] + // TODO(ljj): search result content + }) + Button() { + Image($r('app.media.ic_public_cancel')) + .width('10') + .fillColor($r('app.color.light_fg_shallow')) + } + .width('2%') + .backgroundColor(Color.Transparent) + .onClick(() => { + let index = this.searchHistoryList.indexOf(item[1]); + if (index !== -1) { + this.searchHistoryList.splice(index, 1) + } + }) + } + } else { + if (item.length > 1) { + Text(item[1]) + .width('45%') + .fontSize(14) + .textOverflow({ overflow: TextOverflow.Ellipsis }) + .maxLines(1) + .onClick(() => { + this.searchInput = item[1] + // TODO(ljj): search result content + }) + } + } + }.width('100%') + }) + + } + + } +} \ No newline at end of file diff --git a/scenario/MyNews/entry/src/main/ets/view/Search/TopBar.ets b/scenario/MyNews/entry/src/main/ets/view/Search/TopBar.ets index f9606ee5..2a0be831 100644 --- a/scenario/MyNews/entry/src/main/ets/view/Search/TopBar.ets +++ b/scenario/MyNews/entry/src/main/ets/view/Search/TopBar.ets @@ -32,6 +32,8 @@ function commonBtnStyle(handler?: (event: ClickEvent) => void) { @Component export default struct TopBar { @Prop trendingTopic: string + @Link searchHistoryList: string[] + @Link searchInput: string build() { Row({ space: 5 }) { @@ -46,7 +48,7 @@ export default struct TopBar { }) /* Search box */ - Search({ placeholder: this.trendingTopic }) + Search({ value: $$this.searchInput, placeholder: this.trendingTopic }) .width(0) .height('100%') .flexGrow(1) @@ -64,6 +66,15 @@ export default struct TopBar { .fontColor($r('app.color.primary')) } .commonBtnStyle(() => { + if (this.searchInput === '') { + this.searchInput = this.trendingTopic + } + this.searchInput = this.searchInput.trim() + if (this.searchInput.length) { + this.searchHistoryList.unshift(this.searchInput) + this.searchHistoryList = Array.from(new Set(this.searchHistoryList)) + // TODO(ljj): search result content + } }) } .width('100%') diff --git a/scenario/MyNews/entry/src/main/ets/view/Search/TrendingTopics.ets b/scenario/MyNews/entry/src/main/ets/view/Search/TrendingTopics.ets index 80567d38..f4249a19 100644 --- a/scenario/MyNews/entry/src/main/ets/view/Search/TrendingTopics.ets +++ b/scenario/MyNews/entry/src/main/ets/view/Search/TrendingTopics.ets @@ -19,6 +19,7 @@ @Component export default struct TrendingTopics { @Prop trendingTopicList: string[] + @Link searchInput: string build() { Row() { @@ -27,6 +28,10 @@ export default struct TrendingTopics { .fontSize(14) .textOverflow({ overflow: TextOverflow.Ellipsis }) .maxLines(1) + .onClick(()=>{ + this.searchInput = this.trendingTopicList[0] + // TODO(ljj): search result content + }) Divider() .width('10%') @@ -40,6 +45,10 @@ export default struct TrendingTopics { .fontSize(14) .textOverflow({ overflow: TextOverflow.Ellipsis }) .maxLines(1) + .onClick(()=>{ + this.searchInput = this.trendingTopicList[1] + // TODO(ljj): search result content + }) }.width('100%') } } \ No newline at end of file diff --git a/scenario/MyNews/entry/src/main/resources/base/element/string.json b/scenario/MyNews/entry/src/main/resources/base/element/string.json index 757d75db..060b4770 100644 --- a/scenario/MyNews/entry/src/main/resources/base/element/string.json +++ b/scenario/MyNews/entry/src/main/resources/base/element/string.json @@ -307,6 +307,30 @@ { "name": "article_cmtCnt", "value": "Comments" + }, + { + "name": "search_searchHistory", + "value": "Search History" + }, + { + "name": "search_deleteAll", + "value": "Delete All" + }, + { + "name": "search_deleteAll_finish", + "value": "Finish" + }, + { + "name": "search_deleteAll_dialogPrompt", + "value": "Whether to delete all history" + }, + { + "name": "search_deleteAll_dialogCancel", + "value": "Cancel" + }, + { + "name": "search_deleteAll_dialogConfirm", + "value": "Confirm" } ] } \ No newline at end of file diff --git a/scenario/MyNews/entry/src/main/resources/en_US/element/string.json b/scenario/MyNews/entry/src/main/resources/en_US/element/string.json index 910da9ee..c1e7b58a 100644 --- a/scenario/MyNews/entry/src/main/resources/en_US/element/string.json +++ b/scenario/MyNews/entry/src/main/resources/en_US/element/string.json @@ -307,6 +307,30 @@ { "name": "article_cmtCnt", "value": "Comments" + }, + { + "name": "search_searchHistory", + "value": "Search History" + }, + { + "name": "search_deleteAll", + "value": "Delete All" + }, + { + "name": "search_deleteAll_finish", + "value": "Finish" + }, + { + "name": "search_deleteAll_dialogPrompt", + "value": "Whether to delete all history" + }, + { + "name": "search_deleteAll_dialogCancel", + "value": "Cancel" + }, + { + "name": "search_deleteAll_dialogConfirm", + "value": "Confirm" } ] } \ No newline at end of file diff --git a/scenario/MyNews/entry/src/main/resources/zh_CN/element/string.json b/scenario/MyNews/entry/src/main/resources/zh_CN/element/string.json index bd497e7b..717b51dd 100644 --- a/scenario/MyNews/entry/src/main/resources/zh_CN/element/string.json +++ b/scenario/MyNews/entry/src/main/resources/zh_CN/element/string.json @@ -307,6 +307,30 @@ { "name": "article_cmtCnt", "value": "评论" + }, + { + "name": "search_searchHistory", + "value": "搜索历史" + }, + { + "name": "search_deleteAll", + "value": "全部删除" + }, + { + "name": "search_deleteAll_finish", + "value": "完成" + }, + { + "name": "search_deleteAll_dialogPrompt", + "value": "是否清空搜索历史" + }, + { + "name": "search_deleteAll_dialogCancel", + "value": "取消" + }, + { + "name": "search_deleteAll_dialogConfirm", + "value": "确认" } ] } \ No newline at end of file -- Gitee