c77fb700创建于 2025年1月16日历史提交
/*
 * 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 { router } from '@kit.ArkUI';
import { BusinessError, deviceInfo } from '@kit.BasicServicesKit';
import { image } from '@kit.ImageKit';
import {
  CollaborationServiceFilter,
  CollaborationServiceStateDialog,
  createCollaborationServiceMenuItems
} from '@kit.ServiceCollaborationKit';
import { PhotoManager, ProfileConstants } from '@ohos/photoManager';
import {
  BreakpointType,
  BreakpointTypeEnum,
  CommonConstants,
  FileUtil,
  Logger,
  PlatformInfo,
  PlatformTypeEnum,
  UserAccount
} from '@ohos/utils';
import Constants from '../constants/Constants';

let breakpointType: BreakpointType<string> = new BreakpointType<string>({
  sm: Constants.IMAGE_RATIO_PHONE,
  md: Constants.IMAGE_RATIO_FOLD,
  lg: Constants.IMAGE_RATIO_PAD
})

const TAG = '[PhotoView]';

@Entry({ routeName: 'PhotoView' })
@Component
export struct PhotoView {
  @StorageProp('user') account: UserAccount | null = null;
  @StorageProp('currentBreakpoint') currentBreakpoint: string = BreakpointTypeEnum.MD;
  @StorageProp('profilePixelMap') profilePixelMap: PixelMap | null = null;
  private isPadOr2in1: boolean = (deviceInfo.deviceType === '2in1' || deviceInfo.deviceType === 'tablet');
  private isArkuiX: boolean =
    (PlatformInfo.getPlatform() === PlatformTypeEnum.ANDROID || PlatformInfo.getPlatform() === PlatformTypeEnum.IOS);

  dynamicLoading(): void {
    try {
      import('./ConfirmView');
    } catch (err) {
      Logger.error(TAG, 'dynamicLoading error:' + err);
    }
  }

  aboutToAppear(): void {
    this.dynamicLoading();
  }

  @Builder
  MenuBuilder() {
    Text($r('app.string.use_local_device'))
      .fontColor('#99000000')
      .fontSize($r('app.float.menu_font_size'))
      .padding({ left: $r('app.float.menu_padding') })
      .height($r('app.float.menu_height'))
  }

  @Builder
  SelectProfileMenu() {
    Menu() {
      MenuItem(this.MenuBuilder())
      MenuItem({ content: $r('app.string.select_from_gallery'), startIcon: $r('sys.media.ohos_ic_public_albums') })
        .padding({ left: $r('app.float.menu_padding') })
        .onClick(async () => {
          await PhotoManager.getPhotoManager().selectPicture().then((uri: string) => {
            Logger.info(TAG, 'selectPicture success');
            router.pushNamedRoute({ name: 'ConfirmView', params: new Object({ uri: uri }) });
          }).catch((error: BusinessError) => {
            Logger.info(TAG, 'selectPicture failed, error is ' + JSON.stringify(error));
          });
        })
    }

    Menu() {
      createCollaborationServiceMenuItems([CollaborationServiceFilter.ALL])
    }
  }

  doSavePicture(stateCode: number, _bufferType: string, buffer: ArrayBuffer): void {
    if (stateCode === 0) {
      let imageSource = image.createImageSource(buffer);
      FileUtil.saveBuffer2File(ProfileConstants.getInstance().LOCAL_PROFILE_PATH, buffer);
      FileUtil.saveBuffer2File(ProfileConstants.getInstance().DISTRIBUTED_PROFILE_PATH, buffer);
      imageSource.createPixelMap().then((pixelMap) => {
        AppStorage.setOrCreate('profilePixelMap', pixelMap);
      })
    }
  }

  build() {
    NavDestination() {
      Column() {
        Row() {
          Image($r('app.media.ic_public_cancel'))
            .height($r('app.float.normal_icon_size'))
            .width($r('app.float.normal_icon_size'))
            .fillColor(Color.Blue)
            .onClick(() => {
              router.back();
            })
        }
        .padding({ top: $r('app.float.md_padding_margin') })
        .justifyContent(FlexAlign.Start)
        .width(CommonConstants.FULL_PERCENT)

        Row() {
          Image(this.profilePixelMap !== null ? AppStorage.get<PixelMap>('profilePixelMap') : this.account?.portrait)
            .aspectRatio(1)
            .clipShape(new Circle({ height: Constants.CLIP_RATIO, width: Constants.CLIP_WIDTH })
              .position({
                y: Constants.CIRCLE_RATIO_Y,
                x: Constants.CLIP_MARGIN
              })
            )
        }
        .height(breakpointType.getValue(this.currentBreakpoint))

        if (PlatformInfo.getPlatform() == PlatformTypeEnum.HARMONYOS) {
          CollaborationServiceStateDialog({
            onState: (stateCode: number, bufferType: string, buffer: ArrayBuffer): void => this.doSavePicture(stateCode,
              bufferType, buffer)
          })
        }

        Row() {
          Button($r('app.string.editPhoto'))
            .backgroundColor($r('app.color.back_color'))
            .fontColor($r('app.color.font_color'))
            .type(ButtonType.Capsule)
            .size({
              width: $r('app.float.button_change_width'),
              height: $r('app.float.button_height')
            })
            .margin({ top: $r('app.float.tab_big_img_width') })
            .bindMenu((this.isPadOr2in1 && !this.isArkuiX) ? this.SelectProfileMenu() : undefined)
            .onClick(async () => {
              if (!this.isPadOr2in1) {
                await PhotoManager.getPhotoManager().selectPicture().then((uri: string) => {
                  Logger.info(TAG, 'selectPicture success, uri is ' + uri);
                  router.pushNamedRoute({ name: 'ConfirmView', params: new Object({ uri: uri }) });
                }).catch((error: BusinessError) => {
                  Logger.info(TAG, 'selectPicture failed, error is ' + JSON.stringify(error));
                });
              }
            })
        }
      }
      .backgroundColor(Color.White)
      .height(CommonConstants.FULL_PERCENT)
      .padding({
        top: AppStorage.get<number>('statusBarHeight'),
        bottom: (AppStorage.get<number>('naviIndicatorHeight') || 0) + Constants.PHOTO_PADDING_BOTTOM
      })
    }
    .hideTitleBar(true)
  }
}