Skip to content

Commit

Permalink
initial work
Browse files Browse the repository at this point in the history
  • Loading branch information
Wandalen committed Sep 22, 2024
0 parents commit a1d1731
Show file tree
Hide file tree
Showing 12 changed files with 366 additions and 0 deletions.
32 changes: 32 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@

!/.github
!/.circleci

/binding
/target
/node_modules
/.module
/.data
/package-lock.json
/Cargo.lock
/.vscode
/_*
/.*

.env
_key
_data
target
dist
.module
Cargo.lock
.DS_Store
.idea
*.log
*.db
*.tmp
*.build
*.code-workspace
.warchive*
-*
rustc-ice-*.txt
26 changes: 26 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
[package]
name = "plugin"
version = "0.1.0"
edition = "2021"

[lib]
crate-type = [ "cdylib", "rlib"]

[dependencies]
js-sys = "0.3.61"
wasm-bindgen = "0.2.70"
wasm-bindgen-futures = "0.4.34"
web-sys = { version = "0.3.61", features = [
"Window",
"Document",
"NodeList",
"Element",
"ServiceWorkerGlobalScope",
"Navigator",
"ServiceWorkerContainer",
"ServiceWorker",
"Clients",
"MediaDevices",
"HtmlElement"
] }

Binary file added icon_1024.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added icon_128.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
27 changes: 27 additions & 0 deletions manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"name" : "Tab Lister",
"version" : "1.0",
"manifest_version" : 3,
"description" : "List opened browser tabs in the current window",
"icons" :
{
"128" : "icon_128.png"
},
"permissions" : [ "tabs", "windows", "clipboardWrite" ],
"action" :
{
"default_icon" : "icon_128.png",
"default_popup" : "popup.html"
},
"content_security_policy" : {
"extension_pages": "script-src 'self'; object-src 'self'; style-src 'self' https://cdn.jsdelivr.net https://cdnjs.cloudflare.com;"
},
"web_accessible_resources" : [
{
"resources" : [ "styles.css" ],
"matches" : [ "<all_urls>" ]
}
]
}


64 changes: 64 additions & 0 deletions overview.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# Tab Lister Browser Extension

## Overview

Tab Lister is a lightweight Chrome extension that provides a convenient way to manage and navigate through your open tabs. It displays a list of all currently open tabs in the current window in a compact popup interface, allowing for quick tab switching and easy sharing of tab information in Markdown format.

## Key Features

1. **Tab Listing**: Displays all tabs open in the current window in a scrollable list.
2. **Quick Navigation**: Switch to any listed tab with a single click.
3. **Markdown Export**: Copy all tab titles and URLs in Markdown format for easy sharing or note-taking.
4. **Responsive Design**: Uses Bulma CSS framework for a clean, modern, and mobile-friendly interface.
5. **Compact Interface**: Popup size of 300x500 pixels, suitable for a browser extension.

## Technical Implementation

- **Frontend**: Built with HTML5, CSS3, and vanilla JavaScript.
- **Styling**: Utilizes Bulma CSS framework and Font Awesome icons.
- **Browser API**: Uses the Chrome extension API for tab management.
- **Manifest**: Implements Manifest V3 for enhanced security and performance.

## Functionality

1. **Tab Listing**: On opening, the extension queries all tabs in the current window and renders them in a scrollable list.
2. **Tab Switching**: Clicking on any tab in the list activates that tab in the browser.
3. **Markdown Copy**: The "Copy MD" button allows users to copy all tab information (title and URL) in Markdown format to their clipboard.

## User Interface

- Fixed navbar with the extension title and a "Copy MD" button.
- Scrollable list of tabs, each clickable to switch to that tab.
- Compact design (300x500 pixels) suitable for a browser extension popup.

## How It Works

1. The `popup.html` file defines the structure of the extension's popup interface.
2. `styles.css` and Bulma CSS provide styling for the popup.
3. `popup.js` handles the core functionality:
- Queries open tabs using `chrome.tabs.query`.
- Renders the tab list in the popup.
- Manages tab switching and Markdown copying functionality.

## Installation and Usage

1. Load the extension in Chrome:
- Navigate to `chrome://extensions/`
- Enable "Developer mode"
- Click "Load unpacked" and select the extension directory
2. Click the extension icon in the browser toolbar to open the popup.
3. Click on any tab in the list to switch to it.
4. Use the "Copy MD" button to copy tab information in Markdown format.

## Permissions

- `tabs`: To access and manipulate tab information.
- `clipboardWrite`: To copy tab information to the clipboard.

## Future Enhancements

- Implement tab search functionality.
- Add options for customizing the appearance and behavior.
- Explore cross-browser compatibility (currently Chrome-focused).

Tab Lister aims to streamline tab management, making it easier for users to navigate through multiple open tabs and share their browsing sessions efficiently.
37 changes: 37 additions & 0 deletions popup.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<!DOCTYPE html>
<html>
<head>
<title>Tab Lister</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/css/bulma.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css">
<link rel="stylesheet" href="styles.css">
</head>
<body class="is-flex is-flex-direction-column">
<nav class="navbar is-light is-mobile" role="navigation" aria-label="main navigation">
<div class="navbar-brand">
<a class="navbar-item" href="#">
<strong>Tab Lister</strong>
</a>
<div class="navbar-item is-expanded">
<div class="buttons is-right">
<a id="copyMdButton" class="button is-primary is-small">
<span class="icon is-small">
<i class="fas fa-copy"></i>
</span>
<span>Copy MD</span>
</a>
</div>
</div>
</div>
</nav>
<div class="section is-flex-grow-1 p-2">
<div class="container h-100">
<div class="box h-100 p-2 is-overflow-auto">
<ul id="tabList" class="menu-list"></ul>
</div>
</div>
</div>
<script src="popup.js"></script>
</body>
</html>
53 changes: 53 additions & 0 deletions popup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
document.addEventListener( 'DOMContentLoaded', function()
{
const tabList = document.getElementById( 'tabList' );
const copyMdButton = document.getElementById( 'copyMdButton' );
let tabs = [];

function renderTabs()
{
tabList.innerHTML = '';
tabs.forEach( function( tab )
{
const li = document.createElement( 'li' );
const a = document.createElement( 'a' );

a.href = '#';
a.textContent = tab.title;
a.classList.add( 'has-text-dark', 'py-2' );
a.addEventListener( 'click', function( event )
{
event.preventDefault();
chrome.tabs.update( tab.id, { active: true } );
});

li.appendChild( a );
tabList.appendChild( li );
});
}

function copyAsMarkdown()
{
const markdownList = tabs.map( tab => `- [${tab.title}](${tab.url})` ).join( '\n' );
navigator.clipboard.writeText( markdownList ).then( function()
{
copyMdButton.querySelector( 'span:not(.icon)' ).textContent = 'Copied!';
setTimeout( function()
{
copyMdButton.querySelector( 'span:not(.icon)' ).textContent = 'Copy as MD';
}, 2000 );
}).catch( function( err )
{
console.error( 'Failed to copy text: ', err );
});
}

// Query for tabs in the current window
chrome.tabs.query( { currentWindow: true }, function( queriedTabs )
{
tabs = queriedTabs;
renderTabs();
});

copyMdButton.addEventListener( 'click', copyAsMarkdown );
});
34 changes: 34 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Google Chrome extension

## Abstract

This browser extension provides a convenient way to manage your open tabs:

1. Lists all tabs currently open in the browser window.
2. Displays the list in a popup interface when the extension icon is clicked.
3. Allows quick navigation between tabs directly from the popup.

The extension offers a streamlined view of your open tabs, making it easier to find and switch to the tab you need, especially when you have many tabs open.

## How to run

1. Install [Rust](https://rustup.rs/)
2. Install Wasm-pack
```bash
cargo install wasm-pack
```
3. Run the app
```bash
wasm-pack build --target web
```
4. Open Google Chrome browser and [install the extension](https://support.google.com/chrome_webstore/answer/2664769?hl=en)
5. Press the button to see the URLs in the window

Also [consult](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Your_first_WebExtension#installing).

## How to debug

You may install plugin in your browser as temporary extension. That's easy to do.

- [Temporary Extension in Firefox](https://extensionworkshop.com/documentation/develop/temporary-installation-in-firefox/)
- [Temporary Extension in Chrome](https://webkul.com/blog/how-to-install-the-unpacked-extension-in-chrome/)
16 changes: 16 additions & 0 deletions script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export function getActiveTabUrl( callback )
{
chrome.tabs.query( {}, tabs =>
{
let urls = tabs.map( obj => obj.url );
callback( urls );
});
}

export function changeContent( content )
{
const contentDiv = document.getElementById( 'content');
contentDiv.innerHTML = content;
}

console.log( 'script.js loaded' );
61 changes: 61 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#![ doc = include_str!( "../readme.md" ) ]
use wasm_bindgen::prelude::*;

macro_rules! console_log
{
( $( $t:tt )* ) => ( log( &format_args!( $( $t )* ).to_string() ) )
}

#[ wasm_bindgen ]
extern "C"
{
#[ wasm_bindgen( js_namespace = console ) ]
fn log( s : &str );
}

#[ wasm_bindgen( module = "/script.js" ) ]
extern "C"
{
fn getActiveTabUrl( callback : &Closure< dyn FnMut( Vec< JsValue > ) > );
fn changeContent( content : JsValue );
}

/// this function takes callback from js function and transforms it to pretty view
#[ wasm_bindgen ]
pub fn plugin_entry()
{

// let closure = Closure::wrap(Box::new(|url: JsValue| {
// console_log!("qwe");
// let url_str = url.as_string().unwrap();
// console_log!("{}", url_str);
// }) as Box<dyn Fn(JsValue)>);

let closure = Closure::new( move | url : Vec< JsValue > |
{

console_log!( "{}", "List of tabs :" );

let url_str = url
.into_iter()
.filter_map( | url | url.as_string() )
.collect::< Vec<_> >();
console_log!( "{:?}", url_str );

let pretty_html_list = format!
(
r#"<ul class="styled-list">
{}
</ul>"#,
url_str
.into_iter()
.map( | url | format!( "<li>{url}</li>" ) )
.collect::< Vec<_> >()
.join( "" )
);
changeContent( pretty_html_list.into() );
});

getActiveTabUrl( &closure );
closure.forget();
}
16 changes: 16 additions & 0 deletions styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
body {
width: 300px;
height: 500px;
}

.navbar {
min-height: 40px;
}

.h-100 {
height: 100%;
}

.is-overflow-auto {
overflow: auto;
}

0 comments on commit a1d1731

Please sign in to comment.