/*
* Copyright (c) 2025 Huawei Device Co., Ltd.
* 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.
*/
import {
CustomKeyboardAvoidMode,
DialogBackPressResult,
DialogDismissReason,
DialogHub,
GlobalEvent,
InfCustomDialog,
InfToast
} from 'hadss_dialog';
import type { DialogAction } from 'hadss_dialog';
import { InputCallbackBuilder, InputCallbackParams } from '../component/InputCallbackBuilder';
import { SimpleCustomBuilder, SimpleCustomParams } from '../component/SimpleCustomBuilder';
import { ItemHead } from '../utils/ItemHead';
import { ProgressBuilder, ProgressParams } from '../component/ProgressBuilder';
import { SkipBuilder, SkipParams } from '../component/SkipBuilder';
import { ItemGroupModifier, ItemListModifier, ItemTextModifier } from '../utils/SampleModifier';
import { ActiveCloseBuilder, ActiveCloseParams } from '../component/ActiveCloseBuilder';
import CommonConstant from '../utils/CommonConstant';
import { deviceInfo } from '@kit.BasicServicesKit';
import { resourceManager } from '@kit.LocalizationKit';
import { setWindowPrivacyMode } from '../utils/SafeUtils';
import { window } from '@kit.ArkUI';
@Builder
export function OperableBuilder() {
OperableExample();
}
@Component
export struct OperableExample {
@StorageProp(CommonConstant.TAG_NAME + CommonConstant.CURRENT_BREAK_POINT) curBp: string =
CommonConstant.CURRENT_BREAK_POINT_SM;
pageInfos: NavPathStack = new NavPathStack();
simpleDialog?: InfCustomDialog;
passThroughGestureDialog?: InfToast;
returnDataDialog?: InfCustomDialog;
updateByParentDialog?: InfCustomDialog;
skipDialog?: InfCustomDialog;
intervalID: number = -1;
resourceMgr?: resourceManager.ResourceManager = AppStorage.get(CommonConstant.TAG_NAME + 'resourceMgr');
windowObj?: window.Window = AppStorage.get(CommonConstant.TAG_NAME + 'windowObj');
// [Start back_close]
@State backCloseDialog: boolean = false;
// [End back_close]
@State tagName: string = CommonConstant.TAG_NAME;
@State dialogNum: number = 0; // Number of dialogs on the current page
private dialogNumberListener: GlobalEvent = {
OnCurentPageDialogNumberChange: (newNum: number, oldNum: number) => {
this.dialogNum = newNum;
}
};
aboutToAppear(): void {
setWindowPrivacyMode(true);
this.simpleDialog =
DialogHub.getCustomTemplate(CommonConstant.CUSTOM_TEMPLATE_SIMPLE)
?.setOperableContent(wrapBuilder(SimpleCustomBuilder),
(action: DialogAction) => {
return new SimpleCustomParams(this.getParamString($r('app.string.Dialog3').id),
this.getParamString($r('app.string.NoResponseToBackGesture').id), () => {
action.dismiss();
});
}
)
?.build();
this.simpleDialog?.addLifeCycleListener({
onWillDismiss: (reason: DialogDismissReason) => {
if (this.backCloseDialog && reason === DialogDismissReason.PRESS_BACK) {
return false;
}
return true;
}
});
this.skipDialog = DialogHub.getCustomDialog()
.setOperableContent(wrapBuilder(SkipBuilder), (action: DialogAction) => {
return new SkipParams(() => {
action.dismiss();
}, 0, this.pageInfos);
})
.setConfig({ dialogBehavior: { isModal: true, autoDismiss: false } })
.build();
// [Start add_event]
DialogHub.addEventListener(this.dialogNumberListener);
// [End add_event]
}
aboutToDisappear(): void {
setWindowPrivacyMode(false);
clearInterval(this.intervalID);
this.intervalID = -1;
DialogHub.removeEventListener(this.dialogNumberListener);
}
private getParamString(resourceId: number): string {
if (this.resourceMgr) {
return this.resourceMgr.getStringSync(resourceId);
} else {
return '';
}
}
private createSensorDialog(title: string, isSecondDialog: boolean = false): InfCustomDialog | undefined {
let sensorDialog: InfCustomDialog | undefined =
DialogHub.getCustomTemplate(CommonConstant.CUSTOM_TEMPLATE_SIMPLE)
?.setOperableContent(wrapBuilder(ActiveCloseBuilder),
(action: DialogAction) => {
let param = new ActiveCloseParams(
title,
'',
this.getParamString($r('app.string.Cancel').id),
(isSecondDialog ?
this.getParamString($r('app.string.CloseAllDialog').id) :
this.getParamString($r('app.string.Open').id) +
(title === this.getParamString($r('app.string.Dialog1').id) ?
this.getParamString($r('app.string.Dialog2').id) :
this.getParamString($r('app.string.Dialog1').id)
)
),
() => {
action.dismiss();
},
() => {
if (isSecondDialog) {
DialogHub.getCurrentPageDialogs()
.forEach((dialog) => {
dialog.dismiss();
});
} else {
if (title === this.getParamString($r('app.string.Dialog1').id)) {
this.createSensorDialog(this.getParamString($r('app.string.Dialog2').id), true)?.show();
} else {
this.createSensorDialog(this.getParamString($r('app.string.Dialog1').id), true)?.show();
}
}
},
isSecondDialog ?
(deviceInfo.deviceType === '2in1' ? $r('sys.color.background_primary') : $r('app.color.base_red')) :
undefined
);
return param;
})
.setConfig({ dialogBehavior: { isModal: true, autoDismiss: false, passThroughGesture: false } })
.build();
return sensorDialog;
}
build() {
NavDestination() {
Row() {
List() {
// The custom return gesture is to exit the page or close the popup
ListItem() {
if (this.backCloseDialog) {
ItemHead($r('app.string.currentlyAllocatedDialog'));
} else {
ItemHead($r('app.string.currentlyAllocatedPage'));
}
};
ListItemGroup() {
// Return gesture to the page
ListItem() {
Row() {
Text($r('app.string.break_on_page'))
.attributeModifier(new ItemTextModifier());
Image($r('app.media.chevron_right'))
.height(24)
.opacity(0.2)
.fillColor($r('sys.color.icon_primary'));
};
}
.attributeModifier(new ItemListModifier())
.onClick(() => {
this.backCloseDialog = false;
});
// Return gesture to the dialog
ListItem() {
Row() {
Text($r('app.string.break_on_dialog'))
.attributeModifier(new ItemTextModifier());
Image($r('app.media.chevron_right'))
.height(24)
.opacity(0.2)
.fillColor($r('sys.color.icon_primary'));
};
}
.attributeModifier(new ItemListModifier())
.onClick(() => {
this.backCloseDialog = true;
});
// Simple dialog_1
ListItem() {
Row() {
Text($r('app.string.SHOW_SIMPLE_DIALOG_1'))
.attributeModifier(new ItemTextModifier());
Image($r('app.media.chevron_right'))
.height(24)
.opacity(0.2)
.fillColor($r('sys.color.icon_primary'));
};
}
.attributeModifier(new ItemListModifier())
.onClick(() => {
this.createSensorDialog(this.getParamString($r('app.string.Dialog1').id))?.show();
});
// Simple dialog_2
ListItem() {
Row() {
Text($r('app.string.SHOW_SIMPLE_DIALOG_2'))
.attributeModifier(new ItemTextModifier());
Image($r('app.media.chevron_right'))
.height(24)
.opacity(0.2)
.fillColor($r('sys.color.icon_primary'));
};
}
.attributeModifier(new ItemListModifier())
.onClick(() => {
this.createSensorDialog(this.getParamString($r('app.string.Dialog2').id))?.show();
});
// Non-response Return gesture dialog_3
ListItem() {
Row() {
Text($r('app.string.SHOW_SIMPLE_DIALOG_3'))
.attributeModifier(new ItemTextModifier());
Image($r('app.media.chevron_right'))
.height(24)
.opacity(0.2)
.fillColor($r('sys.color.icon_primary'));
};
}
.attributeModifier(new ItemListModifier())
.onClick(() => {
this.simpleDialog?.show();
});
}.attributeModifier(new ItemGroupModifier());
// Users can manipulate the page through the dialog content
ListItem() {
ItemHead($r('app.string.passThroughGestureDialog'));
};
ListItemGroup() {
// A dialog with passThroughGesture
ListItem() {
Row() {
Text($r('app.string.passThroughGestureDialog'))
.attributeModifier(new ItemTextModifier());
Image($r('app.media.chevron_right'))
.height(24)
.opacity(0.2)
.fillColor($r('sys.color.icon_primary'));
};
}
.attributeModifier(new ItemListModifier())
.onClick(() => {
// [Start pass_through]
let passThroughGestureDialog = DialogHub.getCustomDialog()
.setOperableContent(wrapBuilder(SimpleCustomBuilder), (action: DialogAction) => {
return new SimpleCustomParams(
this.getParamString($r('app.string.Dialog').id),
this.getParamString($r('app.string.passThroughDialog').id),
() => {
action.dismiss();
});
})
.setConfig({
dialogBehavior: {
passThroughGesture: true
}
})
.build();
// [End pass_through]
passThroughGestureDialog.show();
});
}.attributeModifier(new ItemGroupModifier());
// Dialogs interact with the page for data
ListItem() {
ItemHead($r('app.string.dialog_interacts_with_page'));
};
ListItemGroup() {
ListItem() {
Row() {
Text($r('app.string.tagName'))
.margin(CommonConstant.TOP_BOTTOM_MARGIN)
// .width(CommonConstant.FULL_LENGTH)
.textAlign(TextAlign.Center);
Text(this.tagName)
.margin(CommonConstant.TOP_BOTTOM_MARGIN)
// .width(CommonConstant.FULL_LENGTH)
.textAlign(TextAlign.Center);
}
.alignSelf(ItemAlign.Center)
.justifyContent(FlexAlign.SpaceAround)
.alignItems(VerticalAlign.Center);
}
.attributeModifier(new ItemListModifier());
// A dialog that needs to return data to the page
ListItem() {
Row() {
Text($r('app.string.ReturnDataDialog'))
.attributeModifier(new ItemTextModifier());
Image($r('app.media.chevron_right'))
.height(24)
.opacity(0.2)
.fillColor($r('sys.color.icon_primary'));
};
}
.attributeModifier(new ItemListModifier())
.onClick(() => {
// [Start return_content]
this.returnDataDialog = DialogHub.getCustomDialog()
.setOperableContent(wrapBuilder(InputCallbackBuilder), (action: DialogAction) => {
let parms = new InputCallbackParams(CommonConstant.UPDATE_TAG, () => {
action.dismiss();
}, (value) => {
this.tagName = value;
});
return parms;
})
.setConfig({
dialogBehavior: {
isModal: true,
autoDismiss: false,
keyboardAvoidMode: CustomKeyboardAvoidMode.CONTENT_AVOID,
keyboardAvoidSpace: 16
}
})
.build();
this.returnDataDialog.show();
// [End return_content]
});
// The parent page can refresh the dialog content
ListItem() {
Row() {
Text($r('app.string.FatherPageUpdateDialogContent'))
.attributeModifier(new ItemTextModifier());
Image($r('app.media.chevron_right'))
.height(24)
.opacity(0.2)
.fillColor($r('sys.color.icon_primary'));
};
}
.attributeModifier(new ItemListModifier())
.onClick(() => {
// [Start pro_param]
let params = new ProgressParams(this.getParamString($r('app.string.Uploading').id),
CommonConstant.progressNameStart,
CommonConstant.progressNameTotal);
this.updateByParentDialog = DialogHub.getCustomDialog()
.setContent(wrapBuilder(ProgressBuilder), params)
.setConfig({ dialogBehavior: { isModal: true, autoDismiss: false } })
.build();
this.updateByParentDialog.show();
if (this.intervalID >= 0) {
clearInterval(this.intervalID);
this.intervalID = -1;
}
this.intervalID = setInterval(() => {
params.value += 1;
if (params.value >= CommonConstant.progressNameTotal && this.intervalID >= 0) {
this.updateByParentDialog?.dismiss();
clearInterval(this.intervalID);
}
this.updateByParentDialog?.updateContent(params);
}, CommonConstant.Interval_20);
// [End pro_param]
});
}
.attributeModifier(new ItemGroupModifier());
if (this.curBp === CommonConstant.CURRENT_BREAK_POINT_SM) {
// The relationship between dialogs and pages
ListItem() {
ItemHead($r('app.string.DialogWithPage'));
};
ListItem() {
Row() {
Text($r('app.string.numbersOfDialogInCurrentPage'))
.fontWeight(FontWeight.Medium)
.fontSize($r('app.float.font_size_regular'))
.fontColor($r('sys.color.font_primary'))
.margin({ bottom: $r('app.float.now_dialogs_bottom_margin') });
Text(this.dialogNum.toString())
.fontWeight(FontWeight.Medium)
.fontSize($r('app.float.font_size_regular'))
.fontColor($r('sys.color.font_primary'))
.margin({ bottom: $r('app.float.now_dialogs_bottom_margin') });
};
};
ListItemGroup() {
// There is dialog for jump link(Router)
ListItem() {
Row() {
Text($r('app.string.SkipRouter'))
.attributeModifier(new ItemTextModifier());
Image($r('app.media.chevron_right'))
.fillColor($r('sys.color.icon_primary'))
.height(24)
.opacity(0.2);
};
}
.attributeModifier(new ItemListModifier())
.onClick(() => {
let parms = new SkipParams(() => {
this.skipDialog?.dismiss();
}, 0, this.pageInfos);
this.skipDialog?.updateContent(parms);
this.skipDialog?.updateConfig({
dialogPosition: { offset: { dx: 0, dy: 0 } }
});
this.skipDialog?.show();
});
// There is dialog for jump link(Navigation)
ListItem() {
Row() {
Text($r('app.string.SkipNavigation'))
.attributeModifier(new ItemTextModifier());
Image($r('app.media.chevron_right'))
.fillColor($r('sys.color.icon_primary'))
.height(24)
.opacity(0.2);
};
}
.attributeModifier(new ItemListModifier())
.onClick(() => {
// [Start skip_miss]
let parms = new SkipParams(() => {
this.skipDialog?.dismiss();
}, 1, this.pageInfos);
this.skipDialog?.updateContent(parms);
this.skipDialog?.updateConfig({
dialogPosition: { offset: { dx: 0, dy: 0 } }
});
this.skipDialog?.show();
// [End skip_miss]
});
// (widescreen)Display dialog in specific split screens
ListItem() {
Row() {
Text($r('app.string.DifferentPositionShow'))
.attributeModifier(new ItemTextModifier());
Image($r('app.media.chevron_right'))
.fillColor($r('sys.color.icon_primary'))
.height(24)
.opacity(0.2);
};
}
.attributeModifier(new ItemListModifier())
.onClick(() => {
let parms = new SkipParams(() => {
this.skipDialog?.dismiss();
}, 1, this.pageInfos);
this.skipDialog?.updateContent(parms);
this.skipDialog?.updateConfig({
dialogPosition: { offset: { dx: 0, dy: 0 } }
});
this.skipDialog?.show();
});
}
.attributeModifier(new ItemGroupModifier());
} else {
ListItem() {
ItemHead($r('app.string.DialogWithPage'));
};
ListItem() {
Row() {
Text($r('app.string.numbersOfDialogInCurrentPage'))
.fontWeight(FontWeight.Medium)
.fontSize($r('app.float.font_size_regular'))
.fontColor($r('sys.color.font_primary'))
.margin({ bottom: $r('app.float.now_dialogs_bottom_margin') });
Text(this.dialogNum.toString())
.fontWeight(FontWeight.Medium)
.fontSize($r('app.float.font_size_regular'))
.fontColor($r('sys.color.font_primary'))
.margin({ bottom: $r('app.float.now_dialogs_bottom_margin') });
};
};
ListItemGroup() {
// There is dialog for jump link(Router)
ListItem() {
Row() {
Text($r('app.string.SkipRouter'))
.attributeModifier(new ItemTextModifier());
Image($r('app.media.chevron_right'))
.fillColor($r('sys.color.icon_primary'))
.height(24)
.opacity(0.2);
};
}
.attributeModifier(new ItemListModifier())
.onClick(() => {
let parms = new SkipParams(() => {
this.skipDialog?.dismiss();
}, 0, this.pageInfos);
this.skipDialog?.updateContent(parms);
this.skipDialog?.updateConfig({
dialogPosition: { offset: { dx: 0, dy: 0 } }
});
this.skipDialog?.show();
});
// There is dialog for jump link(Navigation)
ListItem() {
Row() {
Text($r('app.string.SkipNavigation'))
.attributeModifier(new ItemTextModifier());
Image($r('app.media.chevron_right'))
.fillColor($r('sys.color.icon_primary'))
.height(24)
.opacity(0.2);
};
}
.attributeModifier(new ItemListModifier())
.onClick(() => {
let parms = new SkipParams(() => {
this.skipDialog?.dismiss();
}, 1, this.pageInfos);
this.skipDialog?.updateContent(parms);
this.skipDialog?.updateConfig({
dialogPosition: { offset: { dx: 0, dy: 0 } }
});
this.skipDialog?.show();
});
// (left)Display dialog in specific split screens
ListItem() {
Row() {
Text($r('app.string.LeftDialog'))
.attributeModifier(new ItemTextModifier());
Image($r('app.media.chevron_right'))
.fillColor($r('sys.color.icon_primary'))
.height(24)
.opacity(0.2);
};
}
.attributeModifier(new ItemListModifier())
.onClick(() => {
// [Start skip_config]
let parms = new SkipParams(() => {
this.skipDialog?.dismiss();
}, 1, this.pageInfos);
this.skipDialog?.updateContent(parms);
this.skipDialog?.updateConfig({
dialogPosition: { offset: CommonConstant.LEFT_DIALOG_OFFSET }
});
this.skipDialog?.show();
// [End skip_config]
});
// (right)Display dialog in specific split screens
ListItem() {
Row() {
Text($r('app.string.RightDialog'))
.attributeModifier(new ItemTextModifier());
Image($r('app.media.chevron_right'))
.fillColor($r('sys.color.icon_primary'))
.height(24)
.opacity(0.2);
};
}
.attributeModifier(new ItemListModifier())
.onClick(() => {
// [Start new_skip]
let parms = new SkipParams(() => {
this.skipDialog?.dismiss();
}, 1, this.pageInfos);
this.skipDialog?.updateContent(parms);
this.skipDialog?.updateConfig({
dialogPosition: { offset: CommonConstant.RIGHT_DIALOG_OFFSET }
});
this.skipDialog?.show();
// [End new_skip]
});
}
.attributeModifier(new ItemGroupModifier());
}
ListItem() {
Stack().width(CommonConstant.FULL_LENGTH).height($r('app.float.item_button_height'));
};
}
.id('first-list')
.width(CommonConstant.FULL_LENGTH)
.height(CommonConstant.FULL_LENGTH)
.scrollBar(BarState.Off);
}
.id('root-row')
.width(CommonConstant.FULL_LENGTH)
.height(CommonConstant.FULL_LENGTH)
.padding({
left: $r('app.float.page_padding'),
right: $r('app.float.page_padding')
});
}
.title($r('app.string.OperableDialogExamples'))
.backgroundColor($r('sys.color.comp_background_gray'))
// [Start back_press]
.onBackPressed(() => {
if (this.backCloseDialog) {
let tmp: DialogBackPressResult = DialogHub.dispatchBackPressToDialog();
if (tmp !== DialogBackPressResult.NO_DIALOG) {
return true;
}
}
this.pageInfos.pop();
return true;
})
// [End back_press]
.onReady((context: NavDestinationContext) => {
this.pageInfos = context.pathStack;
});
}
}