HuaweiLoginView.ets 6.02 KB
import MethodChannel, { MethodCallHandler } from '@ohos/flutter_ohos/src/main/ets/plugin/common/MethodChannel';
import PlatformView, { Params } from '@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformView';
import common from '@ohos.app.ability.common';
import { BinaryMessenger } from '@ohos/flutter_ohos/src/main/ets/plugin/common/BinaryMessenger';
import StandardMethodCodec from '@ohos/flutter_ohos/src/main/ets/plugin/common/StandardMethodCodec';
import MethodCall from '@ohos/flutter_ohos/src/main/ets/plugin/common/MethodCall';
import { loginComponentManager, LoginWithHuaweiIDButton } from '@kit.AccountKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { JSON } from '@kit.ArkTS';
import { hilog } from '@kit.PerformanceAnalysisKit';
import {
  FlutterPlugin,
  FlutterPluginBinding,
  MessageCodec,
  PlatformViewFactory,
  StandardMessageCodec
} from '@ohos/flutter_ohos';

const logTag: string = 'HuaweiLoginComponent';
const domainId: number = 0x0000;
const ERROR_CODE_AGREEMENT_STATUS_NOT_ACCEPTED: number = 1005300001;

class HuaweiLoginInfo {
  public authorizationCode: string = '';
  public openID: string = '';
  public unionID: string = '';
  public idToken: string = '';

  constructor(authorizationCode: string, openID: string, unionID: string, idToken: string) {
    this.authorizationCode = authorizationCode;
    this.openID = openID;
    this.unionID = unionID;
    this.idToken = idToken;
  }
}

@Component
struct HuaweiLoginButton {
  @StorageLink('huaweiAgreementStatus') @Watch('watchAgreementStatus') agreementStatus: boolean = false;
  @StorageLink('huaweiContinueLogin') @Watch('watchContinueLogin') continueLoginFlag: boolean = false;
  @Prop params: Params;
  customView: CustomView = this.params?.platformView as CustomView;

  controller = new loginComponentManager.LoginWithHuaweiIDButtonController()
    .setAgreementStatus(loginComponentManager.AgreementStatus.NOT_ACCEPTED)
    .onClickEvent(() => {
      this.customView.sendMessage('loginStart', '');
    })
    .onClickLoginWithHuaweiIDButton((error: BusinessError, response: loginComponentManager.HuaweiIDCredential) => {
      this.customView.sendMessage('loginEnd', '');
      if (error) {
        hilog.error(domainId, logTag, `HuaweiID login failed. errCode is ${error.code}, message is ${error.message}`);
        if (error.code === ERROR_CODE_AGREEMENT_STATUS_NOT_ACCEPTED) {
          this.customView.sendMessage('agreementNotAccepted', '');
        } else {
          this.customView.sendMessage('loginError', `${error.code}:${error.message}`);
        }
        return;
      }

      const info = new HuaweiLoginInfo(
        response.authorizationCode,
        response.openID,
        response.unionID,
        response.idToken ?? ''
      );
      this.customView.sendMessage('loginSuccess', JSON.stringify(info));
    });

  watchAgreementStatus(): void {
    if (this.agreementStatus) {
      this.controller.setAgreementStatus(loginComponentManager.AgreementStatus.ACCEPTED);
    } else {
      this.controller.setAgreementStatus(loginComponentManager.AgreementStatus.NOT_ACCEPTED);
    }
  }

  watchContinueLogin(): void {
    if (this.continueLoginFlag) {
      this.continueLoginFlag = false;
      this.controller.continueLogin((error: BusinessError) => {
        if (error) {
          hilog.error(domainId, logTag, `continueLogin failed. errCode is ${error.code}, message is ${error.message}`);
          this.customView.sendMessage('loginError', `${error.code}:${error.message}`);
        } else {
          hilog.info(domainId, logTag, 'continueLogin succeeded.');
        }
      });
    }
  }

  build() {
    LoginWithHuaweiIDButton({
      params: {
        style: loginComponentManager.Style.BUTTON_CUSTOM,
        extraStyle: {
          buttonStyle: new loginComponentManager.ButtonStyle().loadingStyle({
            show: true
          })
        },
        loginType: loginComponentManager.LoginType.ID,
        supportDarkMode: true
      },
      controller: this.controller
    }).id('login_with_huaweiId_button')
  }
}

@Builder
function HuaweiLoginButtonBuilder(params: Params) {
  HuaweiLoginButton({ params: params })
}

@Observed
class CustomView extends PlatformView implements MethodCallHandler {
  methodChannel: MethodChannel;

  constructor(context: common.Context, viewId: number, args: Object, message: BinaryMessenger) {
    super();
    this.methodChannel =
      new MethodChannel(message, `com.naji.huawei/loginView${viewId}`, StandardMethodCodec.INSTANCE);
    this.methodChannel.setMethodCallHandler(this);
  }

  onMethodCall(call: MethodCall): void {
    switch (call.method) {
      case 'setAgreementStatus': {
        const value: boolean = call.args as boolean;
        const link: SubscribedAbstractProperty<boolean> = AppStorage.link('huaweiAgreementStatus');
        link.set(value);
        break;
      }
      case 'continueLogin': {
        const link: SubscribedAbstractProperty<boolean> = AppStorage.link('huaweiContinueLogin');
        link.set(true);
        break;
      }
      default: {
        break;
      }
    }
  }

  public sendMessage = (method: string, data: string) => {
    this.methodChannel.invokeMethod(method, data);
  }

  getView(): WrappedBuilder<[Params]> {
    return new WrappedBuilder(HuaweiLoginButtonBuilder);
  }

  dispose(): void {
  }
}

class CustomFactory extends PlatformViewFactory {
  message: BinaryMessenger;

  constructor(message: BinaryMessenger, createArgsCodes: MessageCodec<Object>) {
    super(createArgsCodes);
    this.message = message;
  }

  public create(context: common.Context, viewId: number, args: Object): PlatformView {
    return new CustomView(context, viewId, args, this.message);
  }
}

export default class HuaweiLoginPlugin implements FlutterPlugin {
  getUniqueClassName(): string {
    return 'HuaweiLoginPlugin';
  }

  onAttachedToEngine(binding: FlutterPluginBinding): void {
    binding.getPlatformViewRegistry()?.
      registerViewFactory('com.naji.huawei/loginView', new CustomFactory(binding.getBinaryMessenger(),
        StandardMessageCodec.INSTANCE));
  }

  onDetachedFromEngine(): void {
  }
}