link_cubit.dart 2.15 KB
import 'package:appframe/config/routes.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:webview_flutter/webview_flutter.dart';

class LinkState extends Equatable {
  final bool loaded;
  final String url;
  final String title;

  const LinkState({
    this.loaded = false,
    this.url = '',
    this.title = '',
  });

  LinkState copyWith({
    bool? loaded,
    String? url,
    String? title,
  }) {
    return LinkState(
      loaded: loaded ?? this.loaded,
      url: url ?? this.url,
      title: title ?? this.title,
    );
  }

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

class LinkCubit extends Cubit<LinkState> {
  late final WebViewController _controller;

  WebViewController get controller => _controller;

  LinkCubit(super.initialState) {
    _controller = WebViewController()
      ..setJavaScriptMode(JavaScriptMode.unrestricted)
      ..setNavigationDelegate(
        NavigationDelegate(
          onUrlChange: (UrlChange url) {},
          onPageStarted: (String url) {},
          onPageFinished: (String url) async {
            _controller.runJavaScript(
              'document.querySelector("meta[name=viewport]").setAttribute("content", "width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no")',
            );

            // 如果 state.title 为空,则读取网页的 title
            if (state.title.isEmpty) {
              final pageTitle = await _controller.runJavaScriptReturningResult('document.title') as String?;
              // 移除可能存在的引号
              final cleanTitle = pageTitle?.replaceAll('"', '');
              emit(state.copyWith(title: cleanTitle ?? ''));
            }

            _finishLoading();
          },
        ),
      )
      ..loadRequest(Uri.parse(state.url));
  }

  void _finishLoading() {
    emit(state.copyWith(loaded: true));
  }

  Future<void> handleBack(BuildContext context) async {
    if (await _controller.canGoBack()) {
      _controller.goBack();
    } else {
      // context.pop(true);
      router.pop('ok');
    }
  }
}