Compare commits

..

11 Commits

9 changed files with 655 additions and 691 deletions

View File

@ -1,8 +1,8 @@
# Dropship
> Get Things From One Computer To Another, Safely
> Drag it, drop it, ship it.
[Magic-wormhole](https://magic-wormhole.readthedocs.io/en/latest) with a nice graphical interface.
Dropship is a graphical interface for [Magic-wormhole](https://magic-wormhole.readthedocs.io/en/latest). It allows you to securely send files from one computer to another. Dropship doesn't require any accounts or logging in. Simply select which files you want to send, drop them on the interface and share the resulting password with the receiver. Similarly, to receive a file just enter the received password in Dropship to start receiving a file.
![Screen cast of dropship interface](https://vvvvvvaria.org/~r/dropship0.1.gif)
@ -10,7 +10,12 @@ _(click for video)_
## Features
- ???
- Drag and drop interface
- Manage multiple transfers simultaneously, wheter you are receiving or sending
## Technical
Dropship is built using Python and GTK3.
## Supported Languages
@ -20,7 +25,7 @@ _(click for video)_
Dropship should work on the following distributions:
- Debian Stretch (9.0)
- Debian Bullseye
Other Linux distributions may work as well. We currently do not support MacOS or Windows.
@ -36,9 +41,9 @@ Dropship requires the following system dependencies:
[![PyPI version](https://badge.fury.io/py/dropship.svg)](https://badge.fury.io/py/dropship)
[![Build Status](https://travis-ci.org/decentral1se/dropship.svg?branch=main)](https://travis-ci.org/decentral1se/dropship)
<details><summary>Debian Stretch</summary>
<details><summary>Debian Bullseye</summary>
<pre>
$ sudo apt install -y python3-gi python3-gi-cairo gir1.2-gtk-3.0
$ sudo apt install -y python3-gi python3-cairo-dev python3-gi-cairo gir1.2-gtk-3.0 libglib2.0-dev libgirepository1.0-dev libcairo2-dev
$ python3 -m venv .venv
$ source .venv/bin/activate
$ pip install dropship

View File

@ -1,13 +1,11 @@
from logging import basicConfig, getLogger
from os import environ
from trio import open_nursery, sleep_forever
from trio_gtk import run
from dropship.dropship import DropShip
def main():
"""Trio main entrypoint."""
from dropship.dropship import DropShip
async def _main():
async with open_nursery() as nursery:
@ -17,5 +15,5 @@ def main():
run(_main)
basicConfig(level=environ.get("LOGLEVEL", "INFO"))
log = getLogger("dropship")
if __name__ == "__main__":
main()

View File

@ -1,17 +1,13 @@
from os.path import basename
from pathlib import Path
from gi import require_version
from trio import CancelScope, open_process, run_process
from dropship import log
from dropship.logger import log
require_version("Gtk", "3.0")
require_version("Gdk", "3.0")
from gi.repository import Gdk, GLib, Gtk
from dropship import log
from dropship.constant import UI_DIR
from dropship.transfer import PendingTransfer
from dropship.ui_templates import PendingTransferRow
@ -23,7 +19,7 @@ class DropShip:
def __init__(self, nursery):
"""Object initialisation."""
self.GLADE_FILE = f"{UI_DIR}/dropship_tabless.ui"
self.GLADE_FILE = f"{UI_DIR}/dropship.ui"
self.CSS_FILE = f"{UI_DIR}/dropship.css"
self.clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
@ -80,16 +76,6 @@ class DropShip:
"Cancel", Gtk.ResponseType.CANCEL, "Add", Gtk.ResponseType.OK
)
#sendReceiveStack
self.sendReceiveStack = self.builder.get_object("sendReceiveStack")
#drag and drop in pending view
self.pendingdrop_box = self.builder.get_object("pendingDragDrop")
self.pendingdrop_box.drag_dest_set(
Gtk.DestDefaults.ALL, [self.enforce_target], Gdk.DragAction.COPY
)
self.pendingdrop_box.connect("drag-data-received", self.on_drop)
# Receive UI
# Code entry box
self.recv_box = self.builder.get_object("receiveBoxCodeEntry")
@ -157,8 +143,6 @@ class DropShip:
self._create_pending_transfer(fpath, code, scope)
self.clipboard.set_text(code, -1)
self._send_spinner_off(code)
pending_view = self.sendReceiveStack.get_child_by_name('Pending')
self.sendReceiveStack.set_visible_child(pending_view)
log.info(f"send: successfully initiated transfer send ({code})")
async def receive(self, code):

5
dropship/logger.py Normal file
View File

@ -0,0 +1,5 @@
from logging import basicConfig, getLogger
from os import environ
basicConfig(level=environ.get("LOGLEVEL", "INFO"))
log = getLogger("dropship")

View File

@ -1,261 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.36.0 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkApplicationWindow" id="mainWindow">
<property name="can_focus">False</property>
<property name="resizable">False</property>
<property name="default_width">250</property>
<property name="default_height">250</property>
<child>
<object class="GtkStack" id="sendReceiveStack">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="transition_type">crossfade</property>
<child>
<object class="GtkEventBox" id="dropBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<signal name="button-press-event" handler="add_files" swapped="no"/>
<child>
<object class="GtkBox" id="dragActionContainer">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">16</property>
<property name="margin_right">16</property>
<property name="margin_start">16</property>
<property name="margin_end">16</property>
<property name="margin_top">16</property>
<property name="margin_bottom">16</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkLabel" id="dropLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="valign">center</property>
<property name="label" translatable="yes">Drag a file
drop it here
..and ship it </property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkSpinner" id="dropSpinner">
<property name="can_focus">False</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
<style>
<class name="drop"/>
</style>
</object>
</child>
</object>
<packing>
<property name="name">dragAndDrop</property>
<property name="title" translatable="yes">Send</property>
</packing>
</child>
<child>
<object class="GtkBox" id="receiveBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="homogeneous">True</property>
<child>
<placeholder/>
</child>
<child>
<object class="GtkEntry" id="receiveBoxCodeEntry">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="margin_left">16</property>
<property name="margin_right">16</property>
<property name="primary_icon_stock">gtk-paste</property>
<property name="placeholder_text" translatable="yes">Transfer Code</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="name">receiveView</property>
<property name="title" translatable="yes">Receive</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkEventBox" id="pendingDragDrop">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkBox" id="pendingBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_start">16</property>
<property name="margin_end">16</property>
<property name="margin_top">16</property>
<property name="margin_bottom">16</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_start">6</property>
<property name="margin_end">6</property>
<property name="margin_top">6</property>
<property name="margin_bottom">6</property>
<child>
<object class="GtkLabel" id="dropLabel1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="valign">center</property>
<property name="label" translatable="yes">Drag a file to send</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkEntry" id="receiveBoxCodeEntry1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="primary_icon_stock">gtk-paste</property>
<property name="placeholder_text" translatable="yes">Transfer Code</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="margin_start">6</property>
<property name="margin_end">6</property>
<property name="margin_bottom">6</property>
<property name="hscrollbar_policy">never</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkViewport">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkListBox" id="pendingTransfersList">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<style>
<class name="drop"/>
</style>
</object>
</child>
</object>
<packing>
<property name="name">Pending</property>
<property name="title" translatable="yes">Pending</property>
<property name="position">2</property>
</packing>
</child>
</object>
</child>
<child type="titlebar">
<object class="GtkHeaderBar">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="show_close_button">True</property>
<child>
<placeholder/>
</child>
</object>
</child>
</object>
<object class="GtkFileChooserDialog" id="filePicker">
<property name="can_focus">False</property>
<property name="title" translatable="yes">Choose files to ship</property>
<property name="type_hint">dialog</property>
<property name="transient_for">mainWindow</property>
<property name="has_resize_grip">True</property>
<property name="select_multiple">True</property>
<child internal-child="vbox">
<object class="GtkBox">
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">2</property>
<child internal-child="action_area">
<object class="GtkButtonBox">
<property name="can_focus">False</property>
<property name="layout_style">end</property>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<placeholder/>
</child>
</object>
</child>
<child type="titlebar">
<placeholder/>
</child>
</object>
</interface>

View File

@ -1,49 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.36.0 -->
<!-- Generated with glade 3.38.2 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkImage" id="image1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-no</property>
<property name="icon_size">3</property>
</object>
<template class="pendingTransferRow" parent="GtkListBoxRow">
<property name="width_request">100</property>
<property name="height_request">80</property>
<property name="width-request">100</property>
<property name="height-request">80</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can-focus">True</property>
<property name="activatable">False</property>
<property name="selectable">False</property>
<child>
<object class="GtkBox">
<property name="name">pendingTransmission</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="can-focus">False</property>
<property name="valign">start</property>
<property name="hexpand">True</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_bottom">2</property>
<property name="can-focus">False</property>
<property name="margin-bottom">2</property>
<property name="hexpand">True</property>
<child>
<object class="GtkStack" id="transferStatusStack">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">6</property>
<property name="margin_right">12</property>
<property name="margin_start">6</property>
<property name="margin_end">12</property>
<property name="can-focus">False</property>
<property name="margin-left">6</property>
<property name="margin-right">12</property>
<property name="margin-start">6</property>
<property name="margin-end">12</property>
<child>
<object class="GtkImage">
<property name="width_request">30</property>
<property name="height_request">30</property>
<property name="width-request">30</property>
<property name="height-request">30</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="icon_name">network-transmit</property>
<property name="can-focus">False</property>
<property name="icon-name">sync-synchronizing</property>
<property name="icon_size">5</property>
</object>
<packing>
@ -54,8 +48,8 @@
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="icon_name">dialog-ok</property>
<property name="can-focus">False</property>
<property name="icon-name">folder</property>
<property name="icon_size">5</property>
</object>
<packing>
@ -74,25 +68,27 @@
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_top">6</property>
<property name="margin_bottom">6</property>
<property name="can-focus">False</property>
<property name="margin-top">6</property>
<property name="margin-bottom">6</property>
<property name="hexpand">True</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="can-focus">False</property>
<property name="halign">center</property>
<property name="hexpand">True</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel" id="fileNameLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="can-focus">False</property>
<property name="halign">start</property>
<property name="label" translatable="yes">screenshot_lkashdflasjdjasödjlkasjdlaskdlkashd01-292.jpg</property>
<property name="ellipsize">middle</property>
<property name="max_width_chars">20</property>
<property name="track_visited_links">False</property>
<property name="max-width-chars">20</property>
<property name="track-visited-links">False</property>
<attributes>
<attribute name="weight" value="bold"/>
</attributes>
@ -106,7 +102,7 @@
<child>
<object class="GtkLabel" id="fileNameMetadata">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="can-focus">False</property>
<property name="halign">start</property>
<property name="label" translatable="yes">336 KB</property>
</object>
@ -118,8 +114,8 @@
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="expand">True</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
@ -127,10 +123,10 @@
<object class="GtkButton" id="transferCodeButton">
<property name="label" translatable="yes">5-courier-happening</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<property name="halign">center</property>
<property name="margin_top">6</property>
<property name="margin-top">6</property>
<signal name="clicked" handler="copy_transfer_code" swapped="no"/>
</object>
<packing>
@ -149,23 +145,24 @@
<child>
<object class="GtkStack" id="statusButtonsStack">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">12</property>
<property name="margin_right">6</property>
<property name="margin_start">12</property>
<property name="margin_end">6</property>
<property name="can-focus">False</property>
<property name="margin-left">12</property>
<property name="margin-right">6</property>
<property name="margin-start">12</property>
<property name="margin-end">6</property>
<property name="hhomogeneous">False</property>
<property name="transition_type">crossfade</property>
<property name="transition-type">crossfade</property>
<child>
<object class="GtkButton" id="cancelTransfer">
<property name="label">gtk-cancel</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<property name="halign">center</property>
<property name="valign">center</property>
<property name="margin_top">16</property>
<property name="margin_bottom">16</property>
<property name="image">image1</property>
<property name="margin-top">16</property>
<property name="margin-bottom">16</property>
<property name="use-stock">True</property>
<signal name="clicked" handler="cancel_transfer" swapped="no"/>
<style>
<class name="circular"/>
@ -180,12 +177,12 @@
<object class="GtkButton">
<property name="label" translatable="yes">button</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<property name="halign">center</property>
<property name="valign">center</property>
<property name="margin_top">16</property>
<property name="margin_bottom">16</property>
<property name="margin-top">16</property>
<property name="margin-bottom">16</property>
</object>
<packing>
<property name="name">page1</property>
@ -210,7 +207,7 @@
<child>
<object class="GtkSeparator">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="can-focus">False</property>
</object>
<packing>
<property name="expand">True</property>

View File

@ -1,13 +1,11 @@
from pathlib import Path
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gdk, GLib, Gtk
from dropship import log
from dropship.constant import DEFAULT_DROP_LABEL, UI_DIR
from dropship.logger import log
@Gtk.Template.from_file(f"{UI_DIR}/pendingTransferRow.ui")

View File

@ -2,15 +2,21 @@ from subprocess import PIPE
from trio import TASK_STATUS_IGNORED, CancelScope, open_process, run_process
from dropship import log
from dropship.logger import log
async def wormhole_send(fpath, parent, task_status=TASK_STATUS_IGNORED):
"""Run `wormhole send` on a local file path."""
with CancelScope() as scope:
command = ["wormhole", "send", fpath]
process = await open_process(command, stderr=PIPE)
process = await open_process(command, stderr=PIPE, stdout=PIPE)
output = await process.stderr.receive_some()
#this is some nasty hacky shit
async for i in process.stderr:
if b"On the other computer" in i:
output = i
break
code = output.decode().split()[-1]
task_status.started((code, scope,))
log.info(f"wormhole_send: now waiting for other side ({code})")

916
poetry.lock generated

File diff suppressed because it is too large Load Diff