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 |
+|------------------------------------|---------------------------------------|------------------------------------|----------------------------------|
+|  |  |  |  |
+
+### 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 += `
${productList[i].name}
`; + list += `¥ ${productList[i].price}`; + list += '