diff --git a/README.en.md b/README.en.md new file mode 100644 index 0000000000000000000000000000000000000000..ea3762f54e5555e880776964040be4b173fcdc5f --- /dev/null +++ b/README.en.md @@ -0,0 +1,124 @@ +# Application Continuation (for Browsing Progress) + +### Overview + +This sample implements progress continuation for long list browsing, media browsing, and web page browsing based on the application continuation and distribution capabilities. The long list is implemented by embedding **WaterFlow** in **List**, and **currentOffset** needs to be continued. The media browsing is continued by using AVPlayer, and the **seek()** API is used to continue with an episode stopped at a specific playback time. The web progress is obtained by using the JS statement. + +### Preview + +| Home | Long list | Media | Web | +|------------------------------------|---------------------------------------|------------------------------------|----------------------------------| +| ![image](screenshots/index.en.png) | ![image](screenshots/longlist.en.png) | ![image](screenshots/video.en.png) | ![image](screenshots/web.en.png) | + +### How to Use + +In this sample, three buttons are provided to trigger progress continuation in different scenarios. +1. Long list progress continuation: Tap this button to enter the long list browsing page and complete the progress continuation. +2. Media browsing progress continuation: Tap this button to watch a video and switch from it to another and complete the progress continuation. +3. Web page browsing progress continuation: Tap this button to view the web page and complete the progress continuation. + +### Project Directory + +``` +├──entry/src/main/ets/ +│ ├──entryability +│ │ └──EntryAbility.ets // Entry ability +│ ├──entrybackupability +│ │ └──EntryBackupAbility.ets // Data backup and restoration +│ └──pages +│ └──Index.ets // Home page +├──entry/src/main/resources // App resource directory +├──features/longList/src/main/ets/ +│ ├──constants +│ │ ├──BreakpointConstants.ets // Breakpoint constants +│ │ ├──CommonConstants.ets // Common constants +│ │ └──HomeConstants.ets // Home page constants +│ ├──longlistability +│ │ └──LongListAbility.ets +│ ├──model +│ │ ├──FooterTabData.ets // Data related to the footer tab +│ │ ├──FunctionEntryData.ets // Data for function entries +│ │ ├──FunctionEntryListData.ets // List of data in the function entry +│ │ ├──WaterFlowData.ets // Waterfall data +│ │ ├──WaterFlowDescriptionData.ets // Description data at the bottom of a waterfall item +│ │ ├──WaterFlowHeadData.ets // Header data of a waterfall item +│ │ └──WaterFlowListData.ets // List of waterfall data +│ ├──pages +│ │ └──Index.ets // Page entry +│ ├──utils +│ │ ├──BreakpointSystem.ets // Breakpoint listening +│ │ ├──BreakpointType.ets // Breakpoint type +│ │ ├──Logger.ets // Logger +│ │ └──NetworkUtil.ets // Network request utility +│ └──view +│ ├──FunctionView.ets // Function view +│ ├──HomeContent.ets // Home page +│ ├──IndexNavDestination.ets // Navigation bar entry +│ ├──NavigationBarView.ets // Navigation bar view +│ ├──SearchBarView.ets // Search bar view +│ ├──WaterFlowDescriptionView.ets // View for the description at the bottom of a waterfall item +│ ├──WaterFlowImageView.ets // View for the image description of a waterfall item +│ ├──WaterFlowLivingView.ets // View for the live video description of a waterfall item +│ ├──WaterFlowVideoView.ets // View for the video description of a waterfall item +│ └──WaterFlowView.ets // Waterfall view +├──features/longList/src/main/resources // Resources +├──features/video/src/main/ets/ // Code area +│ ├──components +│ │ ├──ExitVideo.ets // App exit component +│ │ ├──SpeedDialog.ets // Playback speed dialog +│ │ └──VideoOperate.ets // Video operation component +│ ├──pages +│ │ └──Index.ets // Home page +│ ├──utils +│ │ ├──GlobalContext.ets // Context utility +│ │ ├──Logger.ets // Logger +│ │ ├──ResourceUtil.ets // Resource utility +│ │ └──TimeUtils.ets // Video time help utilities +│ ├──videoability +│ │ └──VideoAbility.ets +│ └──videomanager +│ └──AvPlayManager.ets // Video management interface, encapsulating the external functional APIs +├──features/video/src/main/resources // App resource directory +├──features/web/src/main/ets // Code area +│ ├──common +│ │ ├──constants +│ │ │ └──CommonConstants.ets // Common constants +│ │ └──utils +│ │ └──Logger.ets // Logger +│ ├──model +│ │ └──ProductModel.ets // Product model +│ ├──pages +│ │ ├──IndexPage.ets // Home page +│ │ └──OrderConfirmPage.ets // Order confirm page +│ └──webability +│ └──WebAbility.ets +└──features/web/src/main/resources // Resource folder + +``` + +### How to Implement +1. The long list is implemented by embedding **WaterFlow** in **List**, and **currentOffset** needs to be continued. +2. The media browsing is continued with an episode stopped at a specific playback time by using AVPlayer. +3. The web progress is obtained by using the JS statement. + +### Permissions +N/A + +### Dependencies +N/A + +### Constraints + +1. The sample is only supported on Huawei phones with standard systems. + +2. The HarmonyOS version must be HarmonyOS 5.0.0 Release or later. + +3. The DevEco Studio version must be DevEco Studio 5.0.0 Release or later. + +4. The HarmonyOS SDK version must be HarmonyOS 5.0.0 Release SDK or later. + +5. Both devices must be logged in with the same HUAWEI ID. + +6. Wi-Fi and Bluetooth must be enabled on both devices. If the source and target devices are connected to the same LAN, data transmission speed can be improved. + +7. Application continuation can be triggered only between the same application (UIAbility) of both devices, that is, the application must have been installed on the two devices. \ No newline at end of file diff --git a/features/longList/src/main/ets/constants/HomeConstants.ets b/features/longList/src/main/ets/constants/HomeConstants.ets index ae8b7c82f9f2168e53160b6fe0219d7886db2def..5d25809c0a888bc29533e79393c21dd4d4c006ff 100644 --- a/features/longList/src/main/ets/constants/HomeConstants.ets +++ b/features/longList/src/main/ets/constants/HomeConstants.ets @@ -22,7 +22,7 @@ export class HomeConstants { /** * Footer tab english topics. */ - public static readonly FOOTER_TOPIC_LIST_EN: string[] = ['home', 'categorize', 'found', 'shopping', 'mine']; + public static readonly FOOTER_TOPIC_LIST_EN: string[] = ['home', 'categorize', 'found', 'shopping', 'me']; /** * Footer topic icons. diff --git a/features/longList/src/main/ets/view/HomeContent.ets b/features/longList/src/main/ets/view/HomeContent.ets index b12e9d823b68798eaf53924223ffa2b3781e4eda..ebd56f356fb46df52581f8b1bfa799a1d6e4f393 100644 --- a/features/longList/src/main/ets/view/HomeContent.ets +++ b/features/longList/src/main/ets/view/HomeContent.ets @@ -130,7 +130,7 @@ export struct HomeContent { } this.context.startAbility(want) }) - Text('长列表进度接续') + Text($r('app.string.button1')) .fontSize(20) .fontWeight(700) .lineHeight(27) diff --git a/features/longList/src/main/resources/base/element/string.json b/features/longList/src/main/resources/base/element/string.json index 6d86060ee7b1008a207aa608bac1c9cf5b1fe741..a10edebb21c500c33c2ddb34565888bae9876f1d 100644 --- a/features/longList/src/main/resources/base/element/string.json +++ b/features/longList/src/main/resources/base/element/string.json @@ -5,11 +5,11 @@ "value": "module description" }, { - "name": "LongListAbility_label", + "name": "LongListAbility_desc", "value": "description" }, { - "name": "LongListAbility_desc", + "name": "LongListAbility_label", "value": "pageSlip" }, { @@ -47,6 +47,10 @@ { "name": "search", "value": "search..." + }, + { + "name": "button1", + "value": "Long List Continue" } ] } \ No newline at end of file diff --git a/features/longList/src/main/resources/en_US/element/string.json b/features/longList/src/main/resources/en_US/element/string.json index cdd719bc60818376cbc4c44df1ed8e867bdf66d9..6645940ccf9ec89c2c7e3dcd05154f95595fb4a3 100644 --- a/features/longList/src/main/resources/en_US/element/string.json +++ b/features/longList/src/main/resources/en_US/element/string.json @@ -5,11 +5,11 @@ "value": "module description" }, { - "name": "EntryAbility_desc", + "name": "LongListAbility_desc", "value": "description" }, { - "name": "EntryAbility_label", + "name": "LongListAbility_label", "value": "pageSlip" }, { @@ -47,6 +47,10 @@ { "name": "footer_text_max_count", "value": "Reached the bottom" + }, + { + "name": "button1", + "value": "Long List Continue" } ] } \ No newline at end of file diff --git a/features/longList/src/main/resources/zh_CN/element/string.json b/features/longList/src/main/resources/zh_CN/element/string.json index 7c2743031dec047919838435cc184b1a6e28cc36..c524636876a00bd1b452646134861f616f469c7f 100644 --- a/features/longList/src/main/resources/zh_CN/element/string.json +++ b/features/longList/src/main/resources/zh_CN/element/string.json @@ -5,11 +5,11 @@ "value": "模块描述" }, { - "name": "EntryAbility_desc", + "name": "LongListAbility_desc", "value": "描述" }, { - "name": "EntryAbility_label", + "name": "LongListAbility_label", "value": "流畅页面" }, { @@ -47,6 +47,10 @@ { "name": "search", "value": "搜索..." + }, + { + "name": "button1", + "value": "长列表进度接续" } ] } \ No newline at end of file diff --git a/features/web/src/main/ets/pages/IndexPage.ets b/features/web/src/main/ets/pages/IndexPage.ets index 81f19ecf3b657bc288df17baa63678abba71189f..5bcfd0d0e3905a0baf0a5f3b11d09fe2ee72af69 100644 --- a/features/web/src/main/ets/pages/IndexPage.ets +++ b/features/web/src/main/ets/pages/IndexPage.ets @@ -21,15 +21,18 @@ import { common, Want } from '@kit.AbilityKit'; import Logger from '../common/utils/Logger'; import { CommonConstants } from '../common/constants/CommonConstants'; import { ArkTSFunModel } from '../model/ProductModel'; +import { i18n } from '@kit.LocalizationKit'; const TAG: string = '[IndexPage]'; @Entry @Component struct IndexPage { - @StorageLink('continueRestore') continueRestore:boolean = false; - @StorageLink('pageUrl') @Watch('watchPageUrl')pageUrl:string = 'resource://rawfile/product_list.html'; - @StorageLink('scrollDistance')scrollDistance:number = 0; + @StorageLink('continueRestore') continueRestore: boolean = false; + @StorageLink('pageUrl') @Watch('watchPageUrl') pageUrl: string = + i18n.System.getSystemLanguage() === 'zh-Hans' ? 'resource://rawfile/product_list.html' : + 'resource://rawfile/product_list_en.html'; + @StorageLink('scrollDistance') scrollDistance: number = 0; @State webCanBack: boolean = false; @State onPageEnd: boolean = false; @State webCanForward: boolean = false; @@ -37,14 +40,14 @@ struct IndexPage { @State statusBarHeight: number = 0; @State sliderBarHeight: number = 56; private context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; - arkTSObj: ArkTSFunModel = { jumpOrderConfirm: (detailStr: string) => this.jumpOrderConfirm(detailStr) }; - watchPageUrl(){ - if (this.continueRestore){ - this.controller.loadUrl(this.pageUrl); - this.continueRestore = false; + + watchPageUrl() { + if (this.continueRestore) { + this.controller.loadUrl(this.pageUrl); + this.continueRestore = false; } } @@ -88,7 +91,7 @@ struct IndexPage { build() { Stack({ - alignContent:Alignment.TopStart + alignContent: Alignment.TopStart }) { Web({ src: this.pageUrl, controller: this.controller }) .layoutWeight(1) @@ -106,65 +109,70 @@ struct IndexPage { return false; }) .width('100%') - .height(this.pageUrl.includes('product_list')?'90%':'100%') + .height(this.pageUrl.includes('product_list') ? '90%' : '100%') .onPageEnd(async () => { this.webCanBack = this.controller.accessBackward(); this.webCanForward = this.controller.accessForward(); this.onPageEnd = true; - if(this.pageUrl.includes('product_list') && this.continueRestore){ - this.controller.runJavaScript('javascript:document.getElementById("productList").scrollTop = ' + this.scrollDistance); + if (this.pageUrl.includes('product_list') && this.continueRestore) { + this.controller.runJavaScript('javascript:document.getElementById("productList").scrollTop = ' + + this.scrollDistance); } this.pageUrl = this.controller.getUrl(); - let result = await this.controller.runJavaScript('javascript:document.getElementById("productList").scrollTop'); + let result = + await this.controller.runJavaScript('javascript:document.getElementById("productList").scrollTop'); this.scrollDistance = Number(result); }) .zoomAccess(false) .onTouch(async (event: TouchEvent) => { if (event.type === TouchType.Up) { - if(this.pageUrl.includes('product_list')){ - let result = await this.controller.runJavaScript('javascript:document.getElementById("productList").scrollTop'); + if (this.pageUrl.includes('product_list')) { + let result = + await this.controller.runJavaScript('javascript:document.getElementById("productList").scrollTop'); this.scrollDistance = Number(result); } } }) .margin({ - top:this.pageUrl.includes('product_detail')?0:92, + top: this.pageUrl.includes('product_detail') ? 0 : 92, }) - Row(){ + Row() { Image($r('app.media.back')) .width(40) .height(40) .margin({ - right:8 + right: 8 }) - .onClick(()=>{ - if(this.pageUrl.includes('product_list')){ + .onClick(() => { + if (this.pageUrl.includes('product_list')) { let want: Want = { deviceId: '', bundleName: 'com.example.continueprogress', abilityName: 'EntryAbility', } this.context.startAbility(want); - }else if (this.pageUrl.includes('product_detail')){ - this.controller.loadUrl('resource://rawfile/product_list.html'); + } else if (this.pageUrl.includes('product_detail')) { + this.controller.loadUrl(i18n.System.getSystemLanguage() === 'zh-Hans' ? + 'resource://rawfile/product_list.html' : + 'resource://rawfile/product_list_en.html'); } }) - Text('Web页面浏览进度接续') + Text($r('app.string.tittle')) .fontSize(20) .fontWeight(700) .lineHeight(27) } - .backgroundColor(this.pageUrl.includes('product_list')?'#FFF1F3F5':'#00000000') + .backgroundColor(this.pageUrl.includes('product_list') ? '#FFF1F3F5' : '#00000000') .height(56) .width('100%') .alignItems(VerticalAlign.Center) .justifyContent(FlexAlign.Start) .padding({ - left:19, - right:19 + left: 19, + right: 19 }) .margin({ - top:36, + top: 36, }) } .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP]) @@ -172,7 +180,7 @@ struct IndexPage { .height(CommonConstants.FULL_PERCENT) .backgroundColor($r('app.color.common_bg')) .padding({ - bottom:28 + bottom: 28 }) } } \ No newline at end of file diff --git a/features/web/src/main/resources/rawfile/js/product_detail_en.js b/features/web/src/main/resources/rawfile/js/product_detail_en.js new file mode 100644 index 0000000000000000000000000000000000000000..2812810e61b8d46a628028a4f2255a5545b1c258 --- /dev/null +++ b/features/web/src/main/resources/rawfile/js/product_detail_en.js @@ -0,0 +1,100 @@ +let productList = [ + { + 'id': 1, + 'name': 'XX XXXXX XXXXXXXXXXXXXXXXXXXXXX', + 'img': 'imgs/ic_1.png', + 'price': 4488 + }, + { + 'id': 2, + 'name': 'XX XXXXX XXXXXXXXXXXXXXXXXXXXXX', + 'img': 'imgs/ic_2.png', + 'price': 4488 + }, + { + 'id': 3, + 'name': 'XX XXXXX XXXXXXXXXXXXXXXXXXXXXX', + 'img': 'imgs/ic_3.png', + 'price': 4488 + }, + { + 'id': 4, + 'name': 'XX XXXXX XXXXXXXXXXXXXXXXXXXXXX', + 'img': 'imgs/ic_4.png', + 'price': 4488 + }, + { + 'id': 5, + 'name': 'XX XXXXX XXXXXXXXXXXXXXXXXXXXXX', + 'img': 'imgs/ic_5.png', + 'price': 4488 + }, + { + 'id': 6, + 'name': 'XX XXXXX XXXXXXXXXXXXXXXXXXXXXX', + 'img': 'imgs/ic_6.png', + 'price': 4488 + }, + { + 'id': 7, + 'name': 'XX XXXXX XXXXXXXXXXXXXXXXXXXXXX', + 'img': 'imgs/ic_1.png', + 'price': 4488 + }, + { + 'id': 8, + 'name': 'XX XXXXX XXXXXXXXXXXXXXXXXXXXXX', + 'img': 'imgs/ic_2.png', + 'price': 4488 + }, + { + 'id': 9, + 'name': 'XX XXXXX XXXXXXXXXXXXXXXXXXXXXX', + 'img': 'imgs/ic_3.png', + 'price': 4488 + }, + { + 'id': 10, + 'name': 'XX XXXXX XXXXXXXXXXXXXXXXXXXXXX', + 'img': 'imgs/ic_4.png', + 'price': 4488 + }, + { + 'id': 11, + 'name': 'XX XXXXX XXXXXXXXXXXXXXXXXXXXXX', + 'img': 'imgs/ic_5.png', + 'price': 4488 + } +]; + +let urlSearchParams = new URLSearchParams(window.location.search); +let productIndex = urlSearchParams.get('index'); +let productDetail = productList[productIndex]; +productDetail.sku = 'XXX,XGB+XXXGB,XXXXXX,XXXXXXXXXXXXXXXX'; +let swiperStr = ''; +for (let i = 0; i < 3; i++) { + swiperStr += '' +} +document.getElementById('swiper').innerHTML = swiperStr; +document.getElementById('price').innerHTML = '¥ ' + productDetail.price; +document.getElementById('product-name').innerHTML = productDetail.name; + +let currentIndex = 0; +let images = document.querySelectorAll('#swiper img'); + +function showNext() { + var currentImg = document.querySelector('.showing'); + if (currentImg) { + currentImg.classList.remove('showing'); + + currentIndex += 1; + if (currentIndex >= images.length) { + currentIndex = 0; + } + images[currentIndex].classList.add('showing'); + } else { + images[0].classList.add('showing'); + } +} + +setInterval(showNext, 2000); diff --git a/features/web/src/main/resources/rawfile/js/product_list_en.js b/features/web/src/main/resources/rawfile/js/product_list_en.js new file mode 100644 index 0000000000000000000000000000000000000000..000ff92483659ac23936ce6f0c976158272e111b --- /dev/null +++ b/features/web/src/main/resources/rawfile/js/product_list_en.js @@ -0,0 +1,90 @@ +let productList = [ + { + 'id': 1, + 'name': 'XXXXXXX XXXXXXXXXXXXXXXXXXXXXX', + 'img': 'imgs/ic_1.png', + 'price': 4488 + }, + { + 'id': 2, + 'name': 'XXXXXXX XXXXXXXXXXXXXXXXXXXXXX', + 'img': 'imgs/ic_2.png', + 'price': 4488 + }, + { + 'id': 3, + 'name': 'XXXXXXX XXXXXXXXXXXXXXXXXXXXXX', + 'img': 'imgs/ic_3.png', + 'price': 4488 + }, + { + 'id': 4, + 'name': 'XXXXXXX XXXXXXXXXXXXXXXXXXXXXX', + 'img': 'imgs/ic_4.png', + 'price': 4488 + }, + { + 'id': 5, + 'name': 'XXXXXXX XXXXXXXXXXXXXXXXXXXXXX', + 'img': 'imgs/ic_5.png', + 'price': 4488 + }, + { + 'id': 6, + 'name': 'XXXXXXX XXXXXXXXXXXXXXXXXXXXXX', + 'img': 'imgs/ic_6.png', + 'price': 4488 + }, + { + 'id': 7, + 'name': 'XXXXXXX XXXXXXXXXXXXXXXXXXXXXX', + 'img': 'imgs/ic_1.png', + 'price': 4488 + }, + { + 'id': 8, + 'name': 'XXXXXXX XXXXXXXXXXXXXXXXXXXXXX', + 'img': 'imgs/ic_2.png', + 'price': 4488 + }, + { + 'id': 9, + 'name': 'XXXXXXX XXXXXXXXXXXXXXXXXXXXXX', + 'img': 'imgs/ic_3.png', + 'price': 4488 + }, + { + 'id': 10, + 'name': 'XXXXXXX XXXXXXXXXXXXXXXXXXXXXX', + 'img': 'imgs/ic_4.png', + 'price': 4488 + }, + { + 'id': 11, + 'name': 'XXXXXXX XXXXXXXXXXXXXXXXXXXXXX', + 'img': 'imgs/ic_5.png', + 'price': 4488 + } +]; + +function addDocument() { + let list = ''; + for (let i = 0; i < productList.length; i++) { + list += `
  • `; + list += ``; + list += '
    '; + list += `

    ${productList[i].name}

    `; + list += `¥ ${productList[i].price}`; + list += '
    '; + list += '
  • '; + + let tmp = document.getElementById('productList'); + tmp.innerHTML = list; // 添加到div里 + } +} + +addDocument(); + +function jumpDetail(index) { + window.location.href = 'product_detail_en.html?index=' + index; +} diff --git a/features/web/src/main/resources/rawfile/product_detail_en.html b/features/web/src/main/resources/rawfile/product_detail_en.html new file mode 100644 index 0000000000000000000000000000000000000000..03629012939d0b3079d932dbabaeb7a441ea5ddc --- /dev/null +++ b/features/web/src/main/resources/rawfile/product_detail_en.html @@ -0,0 +1,45 @@ + + + + + + + The Canavas Danmu Wall + + +
    +
    + +
    +
    +
    +
    +
    +
    'XX XXXXX XXXXXXXXXXXXXXXXXXXXXX'
    +
    XXXX:
    +
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    + XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    +
    +
    +
    + +
    + + + diff --git a/features/web/src/main/resources/rawfile/product_list_en.html b/features/web/src/main/resources/rawfile/product_list_en.html new file mode 100644 index 0000000000000000000000000000000000000000..3dd4b4713807566223f581e16efbbc61c0a002f5 --- /dev/null +++ b/features/web/src/main/resources/rawfile/product_list_en.html @@ -0,0 +1,16 @@ + + + + + + + The Canavas Danmu Wall + + +
    + +
    + + + diff --git a/features/web/src/main/resources/rawfile/style/product_detail_en.css b/features/web/src/main/resources/rawfile/style/product_detail_en.css new file mode 100644 index 0000000000000000000000000000000000000000..a653c3d902757c2f0cd0a280a0df44b83f9ce381 --- /dev/null +++ b/features/web/src/main/resources/rawfile/style/product_detail_en.css @@ -0,0 +1,158 @@ +body { + margin: 0; +} + +#detail { + width: 100%; + height: 100vh; + background-color: #F1F3F5; + display: flex; + flex-direction: column; + justify-content: space-between; +} + +#detail-info { + flex: 1; + overflow: scroll; +} + +#slider { + width: 100vw; + height:100vw; + background-color: #000000; + overflow: hidden; +} +#swiper { + width: 100vw; + height:100vw; + background-color: #000000; +} + +#swiper > img { + height: 100%; + aspect-ratio: 1.42; + margin: 0px 0 24px 0; + object-fit: cover; + display: none; +} + +.showing { + display: block !important; +} +#dot { + position: absolute; + right: 18px; + top: 68vw; + z-index: 2; + width: 36px; + height: 18px; + border-radius: 9px; + background-color: rgba(0,0,0,0.40); + color: white; + text-align: center; + font-size: 12px; + line-height: 18px; + font-weight: 400; +} + +#info { + margin: 12px; + background-color: #FFFFFF; + border-radius: 16px; + padding: 12px; + color: #182431; +} + +#price { + font-size: 20px; + color: #E92F4F; + line-height: 28px; + font-weight: 500; + margin-top: 4px; +} + +#price > span { + font-size: 14px; +} + +#product-name { + font-size: 16px; + line-height: 21px; + font-weight: 400; + margin-top: 12px; +} + +#guide { + font-size: 14px; + line-height: 20px; + font-weight: 400; + margin-top: 26px; +} + +#product-info { + font-size: 14px; + opacity: 0.6; + text-align: left; + line-height: 20px; + font-weight: 400; + margin-top: 8px; +} + +br { + display: inline; + line-height: 8px; +} + +#menu { + height: 56px; + padding: 0 12px; + align-items: center; + display: flex; + flex-direction: row; +} + +#menu > div { + display: flex; +} + +#menu > div:first-of-type { + flex: 1; + justify-content: space-around; +} + +.btn { + display: flex; + flex-direction: column; +} + +.btn > img { + width: 24px; + height: 24px; +} + +.btn > text { + margin-top: 4px; + font-size: 10px; + text-align: center; + color: #182431; +} + +button { + color: #FFFFFF; + border: none; + height: 40px; + width: 96px +} + +button:first-of-type { + margin-left: 8px; + border-bottom-left-radius: 20px; + border-top-left-radius: 20px; + background: linear-gradient(270deg, #FF914C 52%, #FEA748 96%); +} + +button:last-of-type { + border-bottom-right-radius: 20px; + border-top-right-radius: 20px; + background: linear-gradient(90deg, #F64D43 11%, #EB344D 89%); +} \ No newline at end of file diff --git a/features/web/src/main/resources/rawfile/style/product_list_en.css b/features/web/src/main/resources/rawfile/style/product_list_en.css new file mode 100644 index 0000000000000000000000000000000000000000..400a4965bd579b0ea515e7f572e7f4666634e68e --- /dev/null +++ b/features/web/src/main/resources/rawfile/style/product_list_en.css @@ -0,0 +1,56 @@ +body { + margin: 0; +} + +#container { + width: 100vw; + height: 100vh; + display: flex; + flex-direction: column; +} +#nav { + height: 56px; + font-size: 24px; + color: #182431; + text-align: left; + line-height: 56px; + font-weight: 700; + padding: 0 24px; +} + +ul { + overflow: scroll; + list-style-type: none; + padding: 0; + margin: 0; +} +li { + display: flex; + padding: 8px 24px; +} +li > img { + width: 106px; + aspect-ratio: 1; + border-radius: 18px; +} +li > div { + margin-left: 12px; + flex: 1; +} +li > div > p { + font-size: 14px; + line-height: 19px; + color: #182431; + font-weight: 400; + text-align: justify; +} + +li > div > span { + font-size: 21px; + color: #E92F4F; + line-height: 28px; + font-weight: 500; +} +li > div > span > span { + font-size: 14px; +} \ No newline at end of file diff --git a/screenshots/index.en.png b/screenshots/index.en.png new file mode 100644 index 0000000000000000000000000000000000000000..ab05e66a844908d75522ff323e5f47026a499b99 Binary files /dev/null and b/screenshots/index.en.png differ diff --git a/screenshots/longlist.en.png b/screenshots/longlist.en.png new file mode 100644 index 0000000000000000000000000000000000000000..7e2cfa39560045669be4d1900bc7fcaf0b00c55e Binary files /dev/null and b/screenshots/longlist.en.png differ diff --git a/screenshots/video.en.png b/screenshots/video.en.png new file mode 100644 index 0000000000000000000000000000000000000000..85b1b2fc0193a8d784a66791b2d04ca1cf78c5fe Binary files /dev/null and b/screenshots/video.en.png differ diff --git a/screenshots/web.en.png b/screenshots/web.en.png new file mode 100644 index 0000000000000000000000000000000000000000..ecbdd70429b6498bc8cc4abafdf4ec8158838eac Binary files /dev/null and b/screenshots/web.en.png differ