From c05e81db4f7e4f92e5147690e6e0798b2e7d2073 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alen=20=C5=A0iljak?= <code@alensiljak.eu.org>
Date: Fri, 23 Apr 2021 14:35:56 +0200
Subject: [PATCH] org link handler

---
 lib/core/org_links_handler.dart | 86 +++++++++++++++++++++++++++++++++
 lib/editors/scaffold.dart       | 11 ++---
 2 files changed, 90 insertions(+), 7 deletions(-)
 create mode 100644 lib/core/org_links_handler.dart

diff --git a/lib/core/org_links_handler.dart b/lib/core/org_links_handler.dart
new file mode 100644
index 00000000..916339ef
--- /dev/null
+++ b/lib/core/org_links_handler.dart
@@ -0,0 +1,86 @@
+/*
+Copyright 2020-2021 Alen Šiljak <gitjournal@alensiljak.eu.org>
+
+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 'dart:developer';
+import 'dart:io';
+
+import 'package:org_flutter/org_flutter.dart';
+import 'package:url_launcher/url_launcher.dart';
+
+/// Handles links from .org documents.
+class OrgLinkHandler {
+  String notePath;
+
+  OrgLinkHandler(this.notePath) : super();
+
+  void launchUrl(String link) async {
+    // handle =file:= prefix
+    if (link.startsWith('file:')) {
+      link = link.replaceFirst('file:', '');
+    }
+
+    if (looksLikeImagePath(link)) {
+      // Images
+      if (looksLikeUrl(link)) {
+        // Remote images
+        if (await canLaunch(link)) {
+          await launch(link);
+        } else {
+          //throw 'Could not launch $link';
+          log('could not launch $link');
+        }
+      } else {
+        // (presumably-)Local images
+        File file = File(link);
+
+        if (file.isAbsolute) {
+          // 3. absolute path
+          log('image with absolute path');
+        } else {
+          //log('file exists? ' + file.exists().toString());
+
+          // 1. name-only
+          // 2. relative path
+          log('image ' + file.path);
+        }
+      }
+    } else {
+      // Other links.
+      //
+      if (looksLikeUrl(link)) {
+        // Remote link: Open in system handler.
+        log('url: ' + link);
+
+        if (await canLaunch(link)) {
+          await launch(link);
+        } else {
+          //throw 'Could not launch $link';
+          log('could not launch $link');
+        }
+      } else {
+        // Local file link.
+        File file = File(link);
+        // 1. Only name: Try to find the note with the same name, with or
+        //    without the extension.
+        // 2. Relative path: Open the path, if exists.
+        //    Check if supported extension.
+        // 3. Absolute path: Open if within the repo path?
+        log('note path: ' + notePath);
+        log('local: ' + file.path);
+      }
+    }
+  }
+}
diff --git a/lib/editors/scaffold.dart b/lib/editors/scaffold.dart
index a8e821d7..57420886 100644
--- a/lib/editors/scaffold.dart
+++ b/lib/editors/scaffold.dart
@@ -1,7 +1,5 @@
 // @dart=2.9
 
-import 'dart:developer';
-
 import 'package:flutter/material.dart';
 import 'package:flutter/scheduler.dart';
 
@@ -16,6 +14,7 @@ import 'package:gitjournal/editors/common.dart';
 import 'package:gitjournal/settings.dart';
 import 'package:gitjournal/widgets/note_viewer.dart';
 import 'package:org_flutter/org_flutter.dart';
+import 'package:gitjournal/core/org_links_handler.dart';
 
 class EditorScaffold extends StatefulWidget {
   final Editor editor;
@@ -127,10 +126,6 @@ class _EditorScaffoldState extends State<EditorScaffold> {
     });
   }
 
-  void _launchUrl(String link) async {
-    log('tapped ' + link);
-  }
-
   @override
   Widget build(BuildContext context) {
     var settings = Provider.of<Settings>(context);
@@ -140,9 +135,11 @@ class _EditorScaffoldState extends State<EditorScaffold> {
     } else {
       switch (note.fileFormat) {
         case NoteFileFormat.OrgMode:
+          OrgLinkHandler handler = OrgLinkHandler(note.filePath);
+
           body = Org(
             note.body,
-            onLinkTap: _launchUrl,
+            onLinkTap: handler.launchUrl,
           );
           break;
         default: