14 files changed, 72 insertions(+), 45 deletions(-)
R ISSUES/chrome/{bookmarks.md => help-wanted/bookmarks.md}
R ISSUES/chrome/{clipboard.md => help-wanted/clipboard.md}
R ISSUES/chrome/{history.md => help-wanted/history.md}
R ISSUES/chrome/{topsites.md => help-wanted/topsites.md}
D ISSUES/chrome/reload.md
D ISSUES/chrome/tab-history.md
D ISSUES/docs/stylize_css_reference.md
D ISSUES/docs/update_changelog.md
D ISSUES/docs/update_license.md
M ISSUES/in-progress/links.md
M rhapsode.cabal
M src/Input.hs
M src/Links.hs
M src/Types.hs
R ISSUES/chrome/bookmarks.md => ISSUES/chrome/help-wanted/bookmarks.md +0 -0
R ISSUES/chrome/clipboard.md => ISSUES/chrome/help-wanted/clipboard.md +0 -0
R ISSUES/chrome/history.md => ISSUES/chrome/help-wanted/history.md +4 -1
@@ 1,5 1,8 @@
# History
+**NOTE:** Rhapsode does include history support today, but it's got poor UX.
+Still this existing support is useful as a datasource for a better UX!
+
This page should have a prepopulated "petname".
A single page should be rendered for each day, be punctuated by the hour mark,
-and include navigation links to other years, months, and days.>
\ No newline at end of file
+and include navigation links to other years, months, and days.
R ISSUES/chrome/topsites.md => ISSUES/chrome/help-wanted/topsites.md +0 -0
D ISSUES/chrome/reload.md => ISSUES/chrome/reload.md +0 -2
@@ 1,2 0,0 @@
-# Reload pages
-Important browser feature, especially since the data isn't otherwise live.>
\ No newline at end of file
D ISSUES/chrome/tab-history.md => ISSUES/chrome/tab-history.md +0 -2
@@ 1,2 0,0 @@
-# Navigate back/forward in history
-There should be "psuedo-links" for the last and next visited pages.>
\ No newline at end of file
D ISSUES/docs/stylize_css_reference.md => ISSUES/docs/stylize_css_reference.md +0 -7
@@ 1,7 0,0 @@
-# Stylize HTML included in `css-reference.html` to visually seperate a tag from a description
-
-Currently, the included CSS Reference file is visually difficult to read.
-
-While the software may be developed with Visually Impaired users as a primary target demographic, that does not mean it should shy away from making its end-developer documentation easy to parse both with Rhapsode via audio, *and* visually for those who do not use the software but would like to step up their accessibility game.
-
-This could be achived with some simple HTML5/CSS styling, like changing the background color and changing tag font to Monospace.
D ISSUES/docs/update_changelog.md => ISSUES/docs/update_changelog.md +0 -3
@@ 1,3 0,0 @@
-# Update or Remove the CHANGELOG
-
-The changelog doesn't show anything aside from the initial release version. This should either be updated or removed.
D ISSUES/docs/update_license.md => ISSUES/docs/update_license.md +0 -12
@@ 1,12 0,0 @@
-# Include specific public domain license mechanism in LICENSE for audio
-
-The license file *(as of 6450441)* (in regards to audio files) does not specify a specific strong public domain clause or creative commons license:
-
- ```
- Sound files are in the public domain. The rest of the code, and it's documentation,
- is under the GNU GPL v3+.
- ```
-
-While not strictly necessary for public domain audio works (at least, to my [ariana.giroux@gmail.com] knowledge and in Canada), this is not something that will hold up in court. It is best to include a Creative Commons license that would apply to the audio files. My [ariana.giroux@gmail.com] suggestion would be to utilize a `CC BY` creative commons license.
-
-This license is extremely permissive, only requiring credit back to the original author via derivative and commercial applications. This is already required for the code base via the GPL, so including a similar requirement for the audio files is not a stretch.
M ISSUES/in-progress/links.md => ISSUES/in-progress/links.md +3 -3
@@ 21,9 21,9 @@ These different types of links would be styled differently during the clarificat
- [x] Extract links from page
- [x] Switch to C for access to needed libraries
-- [ ] Filter links based on user input
+- [x] Filter links based on user input
- [ ] Integrate voice recognition (CMU Pocket Sphinx or Mozilla Deep Speech)
-- [ ] Implement "petnames" configured via an XBEL-derived format.
+- [x] Implement "petnames" configured via an XBEL-derived format.
## Petnames
Petnames would be a core part of Rhapsode's "chrome", as this would serve as a
@@ 32,4 32,4 @@ also be the means by which users can access any navigation controls packaged up
with Rhapsode.
It would even give a great experience for unmodified (JS-free) search engines,
-which you could bring up by name and immediately be prompted for a query.>
\ No newline at end of file
+which you could bring up by name and immediately be prompted for a query.
M rhapsode.cabal => rhapsode.cabal +1 -1
@@ 64,7 64,7 @@ library
html-conduit, xml-conduit, text, containers, data-default-class,
network-uri,
stylist >= 2.2 && <3, css-syntax, xml-conduit-stylist >= 2.2 && <3, scientific,
- async, hurl >= 1.4.2.0, filepath, temporary,
+ async, hurl >= 1.5, filepath, temporary,
file-embed >= 0.0.9 && < 0.1, time
-- Directories containing source files.
M src/Input.hs => src/Input.hs +23 -11
@@ 38,17 38,29 @@ import Foreign.C.String
utf8' bytes = convertCharset "utf-8" $ B.toStrict bytes
+fetchDocument http referer mime uri@URI { uriScheme = 'n':'o':'c':'a':'c':'h':'e':'+':scheme } =
+ fetchDocument http { cachingEnabled = False } referer mime uri { uriScheme = scheme }
+fetchDocument http referer mime URI { uriScheme = "app:", uriPath = appID } = do
+ dispatchByApp http Application {
+ name = "", icon = nullURI, description = "",
+ appId = appID
+ } (pageMIME referer) $ Types.url referer
+ return referer -- TODO play an error or success sound
fetchDocument http referer mime uri = fetchURL' http mime uri >>= parseDocument' referer http
-parseDocument' ref sess resp@(_, mime, _) = parseDocument ref sess resp >>= logHistory >>= return . annotate
- where
- annotate x@Page { Types.url = uri'} | Types.url x == uri' = x { pageMIME = mime }
- | ((_, back):backs) <- backStack ref, back == uri' =
- x { pageMIME = mime, backStack = backs, forwardStack = entry x:forwardStack ref }
- | ((_, next):nexts) <- forwardStack ref, next == uri' =
- x { pageMIME = mime, forwardStack = nexts, backStack = entry x:backStack ref }
- | otherwise =
- x { pageMIME = mime, forwardStack = entry x:forwardStack ref, backStack = backStack ref }
- entry x = (pageTitle x, Types.url x)
+
+parseDocument' ref sess resp@(_, mime, _) = do
+ page <- parseDocument ref sess resp >>= logHistory
+ apps' <- appsForMIME sess mime
+ return $ attachHistory $ page { pageMIME = mime, apps = apps' }
+ where
+ attachHistory x@Page { Types.url = uri'} | Types.url x == uri' = x
+ | ((_, back):backs) <- backStack ref, back == uri' =
+ x { backStack = backs, forwardStack = entry x:forwardStack ref }
+ | ((_, next):nexts) <- forwardStack ref, next == uri' =
+ x { forwardStack = nexts, backStack = entry x:backStack ref }
+ | otherwise =
+ x { forwardStack = entry x:forwardStack ref, backStack = backStack ref }
+ entry x = (pageTitle x, Types.url x)
parseDocument ref sess (uri, "html/x-error\t", resp) = parseDocument ref sess (uri, "text/html", resp)
parseDocument _ _ (uri, "text/html", Left text) = pageForDoc uri $ HTML.parseLT $ fromStrict text
parseDocument _ _ (uri, "text/html", Right bytes) = pageForDoc uri $ HTML.parseLBS bytes
@@ 95,7 107,7 @@ pageForText uri txt = pageForDoc uri XML.Document {
}
pageForDoc uri doc = return Page {Types.url = uri, html = doc, css = html2css doc uri,
- pageTitle = "", pageMIME = "", backStack = [], forwardStack = []}
+ pageTitle = "", pageMIME = "", apps = [], backStack = [], forwardStack = []}
logHistory ret@Page {Types.url = url', html = doc} = do
dir <- getXdgDirectory XdgData "rhapsode"
M src/Links.hs => src/Links.hs +37 -1
@@ 13,6 13,11 @@ import Foreign.StablePtr
import Foreign.C.String
import Foreign.Marshal.Array
import Control.Monad (forM)
+import Control.Exception (catch)
+
+import System.Directory -- For locating links.xml
+import System.FilePath
+import System.IO (hPrint, stderr) -- For error reporting
data Link = Link {
label :: Text,
@@ 65,12 70,43 @@ nodesText (NodeContent text:nodes) = text +++ nodesText nodes
nodesText (_:nodes) = nodesText nodes
nodesText [] = ""
+linksFromPage :: Page -> [Link]
+linksFromPage Page {
+ url = url',
+ pageTitle = title',
+ html = html',
+ apps = apps',
+ backStack = back', forwardStack = forward'
+ } = -- TODO internationalize!
+ link' "reload" title' url' :
+ link' "reload without cache" "Fetch again from server without checking for a local copy"
+ url' { uriScheme = "nocache+" ++ uriScheme url' } :
+ [link' "back" t u | (t, u) <- head' back'] ++
+ [link' "forward" t u | (t, u) <- head' forward' ] ++
+ [link' n desc $ URI "app:" Nothing id "" "" | Application n _ desc id <- apps'] ++
+ extractLinks html'
+
+head' (a:_) = [a]
+head' [] = []
+link' l t h = Link (pack l) (pack t) h
+
+readBookmarks :: IO Document
+readBookmarks = do
+ dir <- getXdgDirectory XdgData "rhapsode"
+ let file = dir </> "links.xml"
+ exists <- doesFileExist file
+ if exists then Text.XML.readFile def file `catch` handleInvalid else nodoc
+ where
+ handleInvalid err@(InvalidXMLFile _ _) = hPrint stderr err >> nodoc
+ nodoc = return $ Document (Prologue [] Nothing []) (Element "empty" M.empty []) []
+
-- C API
foreign export ccall c_extractLinks :: StablePtr Page -> IO (CArray CString)
c_extractLinks c_page = do
page <- deRefStablePtr c_page
- ret <- forM (extractLinks $ html page) $ \link -> do
+ bookmarks <- readBookmarks
+ ret <- forM (linksFromPage page ++ extractLinks bookmarks) $ \link -> do
c_label <- text2cstring $ strip $ label link
c_title <- text2cstring $ strip $ title link
c_href <- newCString $ uriToString id (href link) ""
M src/Types.hs => src/Types.hs +4 -2
@@ 1,5 1,5 @@
{-# LANGUAGE OverloadedStrings #-}
-module Types(CArray, Page(..)) where
+module Types(CArray, Page(..), Application(..)) where
import System.Directory (getCurrentDirectory) -- default referer URI
import SpeechStyle (SpeechStyle)
@@ 8,6 8,7 @@ import Data.CSS.Preprocessor.Text (TextStyle)
import Text.XML
import qualified Data.Map.Strict as M
import Network.URI
+import Network.URI.Fetch (Application(..))
import Foreign.Ptr
import Foreign.StablePtr
@@ 20,6 21,7 @@ data Page = Page {
html :: Document,
pageTitle :: String,
pageMIME :: String,
+ apps :: [Application],
backStack :: [(String, URI)],
forwardStack :: [(String, URI)]
}
@@ 39,7 41,7 @@ c_initialReferer = do
documentRoot = Element "temp" M.empty [],
documentEpilogue = []
},
- pageTitle = "", pageMIME = "",
+ pageTitle = "", pageMIME = "", apps = [],
backStack = [], forwardStack = []
}