/*
* Copyright (c) Huawei Technologies Co., Ltd. 2024-2025. All rights reserved.
* 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 common from '@ohos.app.ability.common';
import { vpn } from '@kit.NetworkKit';
import { LogUtil } from '@ohos/settings.common/src/main/ets/utils/LogUtil';
import { DeviceUtil } from '@ohos/settings.common/src/main/ets/utils/BaseUtils';
import { CustomPageComponent } from '@ohos/settings.uikit/src/main/ets/component/CustomPageComponent';
import { ResourceUtil } from '@ohos/settings.common/src/main/ets/utils/ResourceUtil';
import { SystemParamUtils } from '@ohos/settings.common/src/main/ets/screenReader/utils/SystemParamUtils';
import { SwanCtlModel } from './model/SwanCtlModel';
import { VpnListItem } from './model/VpnConfig';
import { VpnConfigModel } from './model/VpnConfigModel';
import { VpnConnectModel } from './model/VpnConnectModel';
import ConfigData from './ConfigData';
import VpnLine from './VpnLine';
import { VpnEditView } from './VpnEditView';
import VpnConstant from './model/VpnConstant';
import { PasswordUtil } from '@ohos/settings.common/src/main/ets/utils/PasswordUtil';
/* instrument ignore file */
const MODULE_TAG: string = 'VpnListComponent:';
@Component
export struct VpnListComponent {
@StorageLink(VpnConstant.STORAGE_KEY_CONNECT_STATE) @Watch('onConnectStateChange') connectState: number =
VpnConstant.VPN_STATE_NONE;
@State vpnList: VpnListItem[] = [];
@State isLoading: boolean = false;
@State isBindSheetShow: boolean = false;
@State isAddVpnEnable: boolean = true;
@Consume('pathInfos') pathInfos: NavPathStack;
isPc: boolean = DeviceUtil.isDevicePc();
isDisableVpn: boolean = SystemParamUtils.getSystemParam('persist.edm.vpn_disable', 'false') === 'true';
async aboutToAppear(): Promise<void> {
LogUtil.info(`${MODULE_TAG} aboutToAppear`);
VpnConfigModel.getInstance().setNeedUpdateVpnList(true);
VpnConnectModel.getInstance().init(getContext() as common.UIAbilityContext);
SwanCtlModel.getInstance().init(getContext() as common.UIAbilityContext);
}
aboutToDisappear(): void {
LogUtil.info(`${MODULE_TAG} aboutToDisappear`);
VpnConnectModel.getInstance().release();
SwanCtlModel.getInstance().release();
}
onShow(): void {
LogUtil.info(`${MODULE_TAG} onShow`);
if (VpnConfigModel.getInstance().isUpdateVpnList()) {
this.updateVpnList();
VpnConfigModel.getInstance().setNeedUpdateVpnList(false);
}
}
async updateVpnList(): Promise<void> {
LogUtil.debug(`${MODULE_TAG} updateVpnList`);
this.isLoading = true;
try {
let data: vpn.SysVpnConfig[] = await vpn.getSysVpnConfigList();
if (data) {
let list = data as VpnListItem[];
let currentVpnId = VpnConnectModel.getInstance().getConnectedVpnId();
list.sort((item1, item2) => {
if (currentVpnId! && item1.vpnId === currentVpnId) {
return -1;
} else if (currentVpnId! && item2.vpnId === currentVpnId) {
return 1;
} else {
return item1.vpnName.localeCompare(item2.vpnName, 'zh');
}
});
this.vpnList = list;
this.isAddVpnEnable = list.length < VpnConstant.VPN_NUM_MAX;
} else {
this.vpnList = [];
}
} catch (err) {
LogUtil.error(`${MODULE_TAG} getSysVpnConfigList failed, err:${err?.message}`);
}
this.isLoading = false;
}
onConnectStateChange(): void {
if (this.connectState === VpnConstant.VPN_STATE_CONNECTED) {
this.updateVpnList();
}
}
build() {
CustomPageComponent({
content: () => {
this.pageContentBuilder()
},
title: ResourceUtil.getStringSync($r('app.string.VPN')),
onPageShow: () => {
this.onShow();
}
})
}
@Builder
pageContentBuilder() {
Column() {
Column() {
Scroll() {
Column() {
if (this.isLoading) {
Column() {
LoadingProgress()
.color($r('sys.color.icon_on_primary'))
.width(80)
}.width('100%').height('100%').justifyContent(FlexAlign.Center).alignItems(HorizontalAlign.Center)
} else {
if (this.vpnList!.length > 0) {
Column() {
List() {
ForEach(this.vpnList, (item: VpnListItem) => {
ListItem() {
VpnLine({
vpnListItem: item
})
}
}, (item: VpnListItem) => JSON.stringify(item));
}
.margin({ top: $r('app.float.margin_8') })
.padding(4)
.align(Alignment.Top)
.borderRadius(this.isPc ? $r('sys.float.corner_radius_level8') :
$r('sys.float.corner_radius_level10'))
.backgroundColor($r('sys.color.comp_background_list_card'))
.divider({
strokeWidth: $r('app.float.divider_stroke_width'),
color: $r('sys.color.comp_divider'),
startMargin: $r('app.float.margin_48'),
endMargin: $r('app.float.margin_8'),
})
}
.width(ConfigData.WH_100_100)
.height(ConfigData.WH_100_100)
.layoutWeight(1)
} else {
Column() {
Image($r('app.media.empty'))
.backgroundColor($r('sys.color.ohos_id_color_background_transparent'))
.width(120)
.height(120)
.draggable(false)
Text($r('app.string.vpn_list_empty'))
.fontColor($r('sys.color.font_secondary'))
.fontSize($r('sys.float.Body_M'))
.fontWeight(FontWeight.Medium)
.fontFamily('HarmonyHeiTi')
}
.justifyContent(FlexAlign.Center)
.width(ConfigData.WH_100_100)
.height(ConfigData.WH_100_100)
.layoutWeight(1)
}
}
}
}
.width('100%')
.edgeEffect(EdgeEffect.Spring)
.scrollable(ScrollDirection.Vertical)
.scrollBar(BarState.Auto)
.layoutWeight(1)
.align(Alignment.TopStart)
Button($r('app.string.vpn_list_add'))
.fontColor($r('sys.color.font_emphasize'))
.fontSize('sys.float.Body_L')
.fontFamily('HarmonyHeiTi')
.fontWeight(FontWeight.Medium)
.backgroundColor($r('sys.color.gray_02'))
.type(ButtonType.Normal)
.borderRadius(this.isPc ? $r('sys.float.corner_radius_level4') :
$r('sys.float.corner_radius_level10'))
.width(this.isPc ? '448vp' : '100%')
.margin({ top: 16, bottom: 16 })
.enabled(this.isAddVpnEnable)
.onClick(() => {
this.isBindSheetShow = true;
})
.visibility(this.isDisableVpn ? Visibility.None : Visibility.Visible)
.bindSheet(this.isBindSheetShow, this.AddBindSheet(), {
height: SheetSize.LARGE,
preferType: this.isPc ? SheetType.CENTER : SheetType.BOTTOM,
showClose: true,
dragBar: false,
title: { title: $r('app.string.vpn_list_add') },
onWillDisappear: () => {
this.isBindSheetShow = false
PasswordUtil.setPrivacyMode(false);
},
onWillAppear: () => {
PasswordUtil.setPrivacyMode(true);
}
})
}
}
.backgroundColor($r('sys.color.comp_background_gray'))
.width(ConfigData.WH_100_100)
.height(ConfigData.WH_100_100)
.padding({ left: this.isPc ? 24 : 16, right: this.isPc ? 24 : 16 })
}
@Builder
AddBindSheet() {
Column() {
VpnEditView({
onSaveClickFinish: () => {
this.updateVpnList();
this.isBindSheetShow = false;
}
})
}
.padding({ top: 8, bottom: this.isPc ? 0 : 32 })
.width(ConfigData.WH_100_100)
.height(ConfigData.WH_100_100)
}
}