ブログにコメント機能のためにutterancesを導入しようとして諦めた話

はじめに

Flutter webで実装してるこのブログにコメント機能が欲しく、utterancesを導入しようとしたが諦めた話をしたいと思います。

もし導入できた方がいましたらTwitterなどで教えていただきたいです(切実に)。

utterancesとは

utterancesとはGithubのissue機能を使って手軽にコメント機能を実装できるオープンソースになります。

導入方法

https://utteranc.es/

上記をConfigurationを通りに進めると script タグは生成されるので、それを導入したいサイトに貼り付けるだけです。
実際に生成されたscriptタグは下記になります。

<script src="https://utteranc.es/client.js"
        repo="idonuntius/blog_comment"
        issue-term="title"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script>

Flutter webでどうもこの script がうまく反映できなかったと思われます。

Flutter Webでの実装方法

大きく下記の2つ方法で実装しました。

dart:uiとdart:htmlを使う

ScriptElementを使ってScriptタグを実装し、platformViewRegistry#registerViewFactory を使ってScriptタグを comment で登録。
build側では HtmlElementView を使って表示させる。

import 'dart:ui' as ui;
import 'dart:html';
// ~~~~~

class CommentWidget extends StatefulWidget {
  @override
  CommentWidgetState createState() => CommentWidgetState();
}

class CommentWidgetState extends State<CommentWidget> {
  final viewType = 'comment'

  @override
  void initState() {
    super.initState();

    ui.platformViewRegistry.registerViewFactory(viewType, (int viewId) {
      final scriptElement = ScriptElement()
        ..src="https://utteranc.es/client.js";
        ..async = true
        ..attributes = {
          'repo': 'idonuntius/blog_comment',
          'issue-term': 'title',
          'theme': 'github-light',
          'crossorigin': 'anonymous',
        };
    }
  }

  @override
  Widget build(BuildContext context) {
    return HtmlElementView(viewType: viewType);
  }
}

HTMLファイルを使ってWebViewで表示させる

WebViewを使用するため webview_flutterwebview_flutter_web を追加。

$ flutter pub add webview_flutter
$ flutter pub add webview_flutter_web

createHtml でHTMLを作成し、それをwebview_flutterを使って表示させる。

class CommentWidget extends StatelessWidgeet {
  WebViewController? _controller;

  @override
  Widget build(BuildContext context) {
    return WebView(
      onWebViewCreated: (WebViewController webViewController) async { 
        _controller = webViewController;
        await _load();
      },
      javascriptMode: JavascriptMode.unrestricted,
    );
  }

  Future<void> _load() {
    _controller?.loadUrl(
      Uri.dataFromString(
        createHtml(),
        mimeType: 'text/html',
        encoding: Encoding.getByName('utf-8'),
      ),
    );
  }

  String createHtml() {
    return '''
    <!DOCTYPE html>
    <html lang="ja">
    <head>
      <title>Comment</title>
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width,initial-scale=1">
    </head>
    <body>
      <script src="https://utteranc.es/client.js"
              repo="idonuntius/blog_comment"
              issue-term="title"
              theme="github-light"
              crossorigin="anonymous"
              async>
      </script>
    </body>
    </html>
    ''';
  }
}

まとめ

今回は大きく2つの方法を試してみましたが、うまくいきませんでした。 もし原因がわかる方、表示することが出来た方は是非Twitterなどで教えていただきたいです。