Opera Speed Dial like chrome

Xerry edited this page Jun 28, 2014 · 4 revisions

Opera Speed Dial is an compact eyecandied bookmark list with thumbnails of the webpages in it. Chrome and Safari adopted it and with firefox there is a plugin offering this functionality. Because with luakit it is possible to create custom chromes, we can add this feature, too.

Requirements

For creating the screenshots you will need external tools:

  • CutyCapt, or any other tool that can render websites to images and
  • ImageMagick's mogrify tool to crop and resize the website screenshots.

The favourite file

The bookmarks will be saved to a favourite file, which should be located at ~/.local/share/luakit/favs. The script below will fail if this file does not exist. Every line of the file describes a bookmark:

[url] [thumbnail-path] [refresh-on-show] [title]

If the thumbnail-path is "none" or refresh-on-show is "on", the script will create a thumbnail as the chrome is shown. For example:

http://luakit.org none no luakit - browser framework
http://reddit.com/r/programming none yes Programming reddit

The Chrome

local chrome = require "chrome" 
local mime = require "mime"
local cutycapt_bin = "/usr/bin/CutyCapt" 
local cutycapt_opt = "--min-width=1920 --min-height=1080" 
local mogrify_bin  = "/usr/bin/mogrify" 
local mogrify_opt  = "-extent 1920x1080 -size 320x180 -resize 320x180" 
local list_path = luakit.data_dir .. "/favs"
local img_path = luakit.data_dir .. "/images"
local page = "luakit://favs/"
local buf, cmd = lousy.bind.buf, lousy.bind.cmd

local css = [==[
    <style type="text/css">
        body {
            background: linear-gradient(to top, #afafaf, #9a9a9a);
            text-align: center;
        }
        a.fav {
            background: #e0e0e0;
            display:inline-block;
            width: 340;
            height:200;
            border: 1px solid black;
            border-radius: 5px;
            padding-top: 10px;
            margin:8px;
            text-align: center;
            text-decoration: none;
            color: black;
            font-weight: bold;
	    box-shadow: 10px 10px 5px #888;
        }
        a.fav:hover {
            background: #f3f3f3;
            border-width:1px;
        }
        a.fav img {
            border: 1px solid #909090;
        }	
    </style>
]==]

local html_template = [==[
	<html>
		<head>
		<title>Speed Dial</title>
   		<meta charset="utf-8">
       		<link href="href='http://fonts.googleapis.com/css?family=Roboto" rel="stylesheet" type="text/css">
			{css}
		</head>
		<body>
			{favs}
		</body>
	</html>
]==]


local fav_template = [==[
    <a class="fav" href={url}><img src={thumb} width="320" height="180" border="0" />{title}</a>
]==]


local function favs()
    local favs = {}
    local updated = {}

    local f = io.open(list_path)
    for line in f:lines() do
        local url, thumb, refresh, title = line:match("(%S+)%s+(%S+)%s+(%S+)%s+(.+)")
        if thumb == "none" or refresh == "yes" then
            thumb = string.format("%s/thumb-%s.jpg", img_path, url:gsub("%W",""))
            local cmd = string.format('%s %s --url="%s" --out="%s" && %s %s %s', cutycapt_bin, cutycapt_opt, url, thumb, mogrify_bin, mogrify_opt, thumb)
            luakit.spawn(string.format("/bin/sh -c '%s'", cmd))
        end
	local img_handle = io.open(thumb, "rb")
	local b = "data:image/jpg;base64," .. mime.b64( img_handle:read( "*a" ) )
	io.close( img_handle )
        updated[#updated+1] = string.format("%s %s %s %s", url, thumb, refresh, title)

        local subs = {
            url   = url,
            thumb = b,
            title = title,
        }
        favs[#favs+1] = fav_template:gsub("{(%w+)}", subs)
    end
    f:close()

    local f = io.open(list_path, "w")
    f:write(table.concat(updated, "\n"))
    f:close()

    return table.concat(favs, "\n")
end

chrome.add("favs", function (view, meta)
    -- the file:// is neccessary so that the thumbnails will be shown.
    -- disables reload though.
    local template = string.gsub(html_template, "{css}", css)
    local html = string.gsub(template, "{favs}", favs())
    view:load_string(html, "luakit://favs/")
end )

----------------------------------------------------------------------

add_binds("normal", {
    buf("^gs$",
        [[Open [luakit://favs](luakit://favs/) in current tab.]],
        function (w) w:navigate(page) end),

    buf("^gS$",
        [[Open [luakit://favs](luakit://favs/) in new tab.]],
        function (w) w:new_tab(page) end),
})

add_cmds({
    cmd("favs",
        [[Open [luakit://favs](luakit://favs/) in new tab.]],
        function (w) w:new_tab(page) end),
})