web_cubit.dart 4.33 KB
import 'dart:convert';
import 'dart:io';

import 'package:appframe/data/models/message/h5_message.dart';
import 'package:appframe/services/dispatcher.dart';
import 'package:appframe/services/local_server_service.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:webview_flutter/webview_flutter.dart';

class WebState extends Equatable {
  final bool loaded;
  final String title;

  final bool needAuth;
  final String? sessionCode;
  final String? userCode;
  final String? classCode;
  final int? userType;
  final String? stuId;

  const WebState(
    this.loaded,
    this.title,
    this.needAuth,
    this.sessionCode,
    this.userCode,
    this.classCode,
    this.userType,
    this.stuId,
  );

  WebState copyWith({
    bool? loaded,
    String? title,
    bool? needAuth,
    String? sessionCode,
    String? userCode,
    String? classCode,
    int? userType,
    String? stuId,
  }) {
    return WebState(
      loaded ?? this.loaded,
      title ?? this.title,
      needAuth ?? this.needAuth,
      sessionCode ?? this.sessionCode,
      userCode ?? this.userCode,
      classCode ?? this.classCode,
      userType ?? this.userType,
      stuId ?? this.stuId,
    );
  }

  @override
  List<Object?> get props => [loaded, title, needAuth];
}

class WebCubit extends Cubit<WebState> {
  late final MessageDispatcher _dispatcher;
  late final WebViewController _controller;
  late final HttpServer _server;

  WebViewController get controller => _controller;

  WebCubit(super.initialState) {
    // 消息处理器
    _dispatcher = MessageDispatcher();

    // WebView控制器
    _controller = WebViewController()
      ..setJavaScriptMode(JavaScriptMode.unrestricted)
      ..setNavigationDelegate(
        NavigationDelegate(
          onUrlChange: (UrlChange url) {
            print('onUrlChange===${url.url}');
          },
          onPageStarted: (String url) {
            // 进行新页面加载时,关闭录音器和播放器,(如果有打开过)
            // closeLocalRecorder() ;
            // closeLocalPlayer();
          },
          onPageFinished: (String url) {
            print("onPageFinished-------------------------$url");
            finishLoading();
          },
        ),
      )
      ..addJavaScriptChannel("xeJsBridge", onMessageReceived: _onMessageReceived);

    // 启动本地服务器,并加载HTML
    _startLocalServerAndLoadHtml();
  }

  _startLocalServerAndLoadHtml() async {
    // 启动本地服务器
    _server = await LocalServerService().startLocalServer();

    final String serverUrl;
    if (state.sessionCode == null || state.sessionCode == '') {
      serverUrl = 'http://127.0.0.1:${_server.port}/test/test.html';
    } else {
      serverUrl =
          'http://127.0.0.1:${_server.port}/index.html#/h5/login/pages/applogin?sessionCode=${state.sessionCode}&userCode=${state.userCode}&classCode=${state.classCode}&userType=${state.userType}&stuId=${state.stuId}';
    }

    print("serverUrl===$serverUrl");

    _controller.loadRequest(Uri.parse(serverUrl));
  }

  _onMessageReceived(JavaScriptMessage message) async {
    try {
      final Map<String, dynamic> data = json.decode(message.message);
      H5Message h5Message = H5Message.fromJson(data);

      _dispatcher.dispatch(h5Message, (response) {
        _sendResponse(response);
      });
    } catch (e) {
      print('消息解析错误: $e');
    }
  }

  // 向H5发送响应
  void _sendResponse(Map<String, dynamic> response) {
    String jsonString = jsonEncode(response);
    String escapedJson = jsonString.replaceAll('"', '\\"');
    final String script = 'xeJsBridgeCallback("$escapedJson");';
    _controller.runJavaScript(script);
  }

  void finishLoading() {
    emit(state.copyWith(loaded: true, title: '班小二测试H5'));
  }

  // 测试
  void setTitle(String title) {
    emit(state.copyWith(title: title));
  }

  // 测试
  void resetLoading() {
    emit(state.copyWith(loaded: false, title: '界面加载中...'));
  }

  //测试
  void goAuth() {
    emit(state.copyWith(needAuth: true));
  }

  //测试
  void goAuth2() {
    print("iOS 测试-------------------");
    String serverUrl = 'http://127.0.0.1:${_server.port}/index.html';
    _controller.loadRequest(Uri.parse(serverUrl));
  }

  @override
  Future<void> close() async {
    _server.close();
    return super.close();
  }
}