Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dev #63

Merged
merged 8 commits into from
Aug 3, 2024
Merged

Dev #63

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,19 +55,25 @@ The "Packages" directory is located at:
* OS X:

```bash
~/Library/Application Support/Sublime Text/Packages
~/Library/Application Support/Sublime Text/Packages/
# or
~/Library/Application Support/Sublime Text/Installed Packages/
```

* Linux:

```bash
~/.config/sublime-text/Packages/
# or
~/.config/sublime-text/Installed Packages/
```

* Windows:

```bash
%APPDATA%/Sublime Text/Packages/
# or
%APPDATA%/Sublime Text/Installed Packages/
```

## Configuration
Expand Down Expand Up @@ -107,7 +113,7 @@ After setting them it will download the notes.
Hit the shortcut again after the download is done (check the message bar) and it will **show a list of the notes**:
![Alt Notes](assets/images/note_list.png "Note List")

It will download notes every time sublime text is launched and every now and then if the _sync_every_ configuration is enabled (has a positive value), so take a look at the bar to check the status.
It will download notes every time sublime text is launched and every now and then if the _sync_interval_ configuration is enabled (has a positive value), so take a look at the bar to check the status.

If a note gets updated from somewhere else
![Alt External Update](http://i.imgur.com/p9pAY6z.png "External Update")
Expand Down
4 changes: 2 additions & 2 deletions Simplenote.sublime-settings
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
// --------------------------------
// Sync when sublime text starts:
,"autostart": true
// Sync automatically (in seconds)
,"sync_every": 30
// Sync automatically interval (in seconds)
,"sync_interval": 30
// Number of notes synchronized each time
,"sync_note_number": 1000
// Conflict resolution (If a file was edited on another client and also here, on sync..)
Expand Down
6 changes: 3 additions & 3 deletions _config.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
// Sync when sublime text starts:
,"autostart": true
// Sync automatically (in seconds)
,"sync_every": 30
,"sync_interval": 30
// Number of notes synchronized each time
,"sync_note_number": 1000
// Conflict resolution (If a file was edited on another client and also here, on sync..)
Expand Down Expand Up @@ -133,8 +133,8 @@ def __init_subclass__(cls, **kwargs):
SIMPLENOTE_NOTES_DIR = os.path.join(SIMPLENOTE_CACHE_DIR, "notes")
os.makedirs(SIMPLENOTE_NOTES_DIR, exist_ok=True)

# SIMPLENOTE_STARTED: bool = False
# SIMPLENOTE_RELOAD_CALLS: int = -1
SIMPLENOTE_STARTED_KEY: str = "simplenote_started"
SIMPLENOTE_SYNC_TIMES_KEY: str = "simplenote_sync_times"


class Development(_BaseConfig):
Expand Down
77 changes: 26 additions & 51 deletions commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
import sublime_plugin

from ._config import CONFIG
from .lib.core import start
from .lib.gui import clear_orphaned_filepaths, close_view, on_note_changed, open_view, show_message
from .lib.core import GlobalStorage, sync_once
from .lib.gui import close_view, on_note_changed, open_view, show_message, show_quick_panel
from .lib.models import Note
from .lib.operations import NoteCreator, NoteDeleter, NotesIndicator, NoteUpdater, OperationManager

Expand All @@ -25,7 +25,7 @@
logger = logging.getLogger()


SIMPLENOTE_STARTED = False
global_storage = GlobalStorage()


class SimplenoteViewCommand(sublime_plugin.EventListener):
Expand All @@ -34,7 +34,6 @@ class SimplenoteViewCommand(sublime_plugin.EventListener):

@cached_property
def autosave_debounce_time(self) -> int:
logger.warning(("CONFIG.SIMPLENOTE_SETTINGS_FILE_PATH", CONFIG.SIMPLENOTE_SETTINGS_FILE_PATH))
settings = sublime.load_settings(CONFIG.SIMPLENOTE_SETTINGS_FILE_PATH)
_autosave_debounce_time = settings.get("autosave_debounce_time", 1)
if not isinstance(_autosave_debounce_time, int):
Expand Down Expand Up @@ -123,53 +122,11 @@ def on_post_save(self, view: sublime.View):

class SimplenoteListCommand(sublime_plugin.ApplicationCommand):

def on_select(self, selected_index: int):
if selected_index == -1:
return
note_id = self.list__modificationDate[selected_index]
selected_note = Note.tree.find(note_id)
if not isinstance(selected_note, Note):
show_message("Note not found: note id(%s), Please restart simplenote or sublime text." % note_id)
return
filepath = selected_note.open()
selected_note.flush()
view = open_view(filepath)

def run(self):
global SIMPLENOTE_STARTED
if not SIMPLENOTE_STARTED:
if not start():
return

if Note.tree.count <= 0:
show_message(
"No notes found. Please wait for the synchronization to complete, or press [super+shift+s, super+shift+c] to create a note."
)
self.list__modificationDate: List[float] = []
self.list__title: List[str] = []
list__filename: List[str] = []
for note in Note.tree.iter(reverse=True):
if not isinstance(note, Note):
raise Exception("note is not a Note: %s" % type(note))
if note.d.deleted == True:
continue
self.list__modificationDate.append(note.d.modificationDate)
self.list__title.append(note.title)
list__filename.append(note.filename)

# TODO: Maybe doesn't need to run every time
clear_orphaned_filepaths(list__filename)

def show_panel():
sublime.active_window().show_quick_panel(
self.list__title,
self.on_select,
flags=sublime.KEEP_OPEN_ON_FOCUS_LOST,
# on_highlight=self.on_select,
placeholder="Select Note press key 'enter' to open",
)

sublime.set_timeout(show_panel, 50)
if Note.tree.count:
show_quick_panel()
if not global_storage.get(CONFIG.SIMPLENOTE_STARTED_KEY):
sync_once()


class SimplenoteSyncCommand(sublime_plugin.ApplicationCommand):
Expand All @@ -179,14 +136,32 @@ def merge_note(self, updated_notes: List[Note]):
if note.need_flush:
on_note_changed(note)

def callback(self, updated_notes: List[Note]):
self.merge_note(updated_notes)

sync_times = global_storage.get(CONFIG.SIMPLENOTE_SYNC_TIMES_KEY)
if not isinstance(sync_times, int):
raise TypeError(
"Value of %s must be type %s, got %s" % (CONFIG.SIMPLENOTE_SYNC_TIMES_KEY, int, type(sync_times))
)
first_sync = sync_times == 0
if first_sync:
show_quick_panel(first_sync)
global_storage.optimistic_update(CONFIG.SIMPLENOTE_SYNC_TIMES_KEY, sync_times + 1)
global_storage.optimistic_update(CONFIG.SIMPLENOTE_STARTED_KEY, False)

def run(self):
if global_storage.get(CONFIG.SIMPLENOTE_STARTED_KEY):
return
global_storage.optimistic_update(CONFIG.SIMPLENOTE_STARTED_KEY, True)

settings = sublime.load_settings(CONFIG.SIMPLENOTE_SETTINGS_FILE_PATH)
sync_note_number = settings.get("sync_note_number", 1000)
if not isinstance(sync_note_number, int):
show_message("`sync_note_number` must be an integer. Please check settings file.")
return
note_indicator = NotesIndicator(sync_note_number=sync_note_number)
note_indicator.set_callback(self.merge_note)
note_indicator.set_callback(self.callback)
OperationManager().add_operation(note_indicator)


Expand Down
4 changes: 4 additions & 0 deletions dev_deploy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# local development deploy
zip -r Simplenote.sublime-package . -x ".env*" ".git/*" ".github/*" ".gitignore" ".idea/*" ".vscode/*" ".pytest_cache/*" "pyproject.toml" "package-lock.json" "package.json" "node_modules/*" ".env.*" ".DS_Store" "assets/*" "*__pycache__/*" "tmp/*" "tests/*" "logs/*" "sublime_api.py" "dev_deploy.sh" "package-metadata.json"

mv Simplenote.sublime-package $HOME/Library/Application\ Support/Sublime\ Text/Installed\ Packages/Simplenote.sublime-package
61 changes: 40 additions & 21 deletions lib/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,44 +3,63 @@
import sublime

from .._config import CONFIG
from ..utils.lock.thread import OptimisticLockingDict
from ..utils.patterns.singleton.base import Singleton
from .gui import edit_settings, remove_status, show_message
from .operations import OperationManager


logger = logging.getLogger()
SIMPLENOTE_STARTED = False


def sync():
manager = OperationManager()
class GlobalStorage(Singleton, OptimisticLockingDict):
__mapper_key_type = {CONFIG.SIMPLENOTE_SYNC_TIMES_KEY: int, CONFIG.SIMPLENOTE_STARTED_KEY: bool}

def optimistic_update(self, key, new_value):
_type = self.__mapper_key_type.get(key)
if not _type is None:
if not isinstance(new_value, _type):
raise TypeError("Value of %s must be type %s, got %s" % (key, _type, type(new_value)))

if key == CONFIG.SIMPLENOTE_SYNC_TIMES_KEY:
import time

logger.warning((time.time(), key, new_value))
return super().optimistic_update(key, new_value)


manager = OperationManager()
global_storage = GlobalStorage()


def sync_once():
if not manager.running:
sublime.run_command("simplenote_sync")
else:
logger.debug("Sync omitted")

settings = sublime.load_settings(CONFIG.SIMPLENOTE_SETTINGS_FILE_PATH)
sync_every = settings.get("sync_every", 0)
logger.debug(("Simplenote sync_every", sync_every))
if not isinstance(sync_every, int):
show_message("`sync_every` must be an integer. Please check settings file.")
return

if sync_every > 0:
sublime.set_timeout(sync, sync_every * 1000)
def sync(sync_interval: int = 30):
sync_once()
sublime.set_timeout(sync, sync_interval * 1000)


def start():
global SIMPLENOTE_STARTED
settings = sublime.load_settings("Simplenote.sublime-settings")
settings = sublime.load_settings(CONFIG.SIMPLENOTE_SETTINGS_FILE_PATH)
username = settings.get("username")
password = settings.get("password")

if username and password:
sync()
SIMPLENOTE_STARTED = True
else:
edit_settings()
show_message("Simplenote: Please configure username/password, Please check settings file.")
sublime.set_timeout(remove_status, 2000)
SIMPLENOTE_STARTED = False
return SIMPLENOTE_STARTED
if global_storage.get(CONFIG.SIMPLENOTE_SYNC_TIMES_KEY) != 0:
return
sync_interval = settings.get("sync_interval", 30)
if not isinstance(sync_interval, int):
show_message("`sync_interval` must be an integer. Please check settings file.")
return
if sync_interval <= 0:
return
sync(sync_interval)
return
show_message("Simplenote: Please configure username/password in settings file.")
edit_settings()
sublime.set_timeout(remove_status, 2000)
50 changes: 50 additions & 0 deletions lib/gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"close_view",
"clear_orphaned_filepaths",
"on_note_changed",
"show_quick_panel",
]


Expand Down Expand Up @@ -121,3 +122,52 @@ def on_note_changed(note: Note):
old_window.focus_view(old_active_view)

sublime.set_timeout(partial(new_view.run_command, "revert"), 0)


def on_select(list__modificationDate: List[float], selected_index: int):
if selected_index == -1:
return
note_id = list__modificationDate[selected_index]
selected_note = Note.tree.find(note_id)
if not isinstance(selected_note, Note):
show_message("Note not found: note id(%s), Please restart simplenote or sublime text." % note_id)
return
filepath = selected_note.open()
selected_note.flush()
view = open_view(filepath)


def show_quick_panel(first_sync: bool = False):
if Note.tree.count <= 0:
show_message(
"No notes found. Please wait for the synchronization to complete, or press [super+shift+s, super+shift+c] to create a note."
)
list__modificationDate: List[float] = []
list__title: List[str] = []
list__filename: List[str] = []
for note in Note.tree.iter(reverse=True):
if not isinstance(note, Note):
raise Exception("note is not a Note: %s" % type(note))
if note.d.deleted == True:
continue
list__modificationDate.append(note.d.modificationDate)
list__title.append(note.title)
list__filename.append(note.filename)

# TODO: Maybe doesn't need to run every time
clear_orphaned_filepaths(list__filename)

placeholder = "Select Note press key 'enter' to open"
if first_sync:
placeholder = "Sync complete. Press [super+shift+s] [super+shift+l] to display the note list again."

def show_panel():
sublime.active_window().show_quick_panel(
list__title,
partial(on_select, list__modificationDate),
flags=sublime.MONOSPACE_FONT,
# on_highlight=self.on_select,
placeholder=placeholder,
)

sublime.set_timeout(show_panel, 500)
27 changes: 15 additions & 12 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,43 +3,46 @@
import sublime

from ._config import CONFIG
from .lib.core import start
from .lib.core import GlobalStorage, start
from .lib.gui import show_message
from .lib.models import Note


logger = logging.getLogger()

SIMPLENOTE_RELOAD_CALLS = -1

global_storage = GlobalStorage()
global_storage.optimistic_update(CONFIG.SIMPLENOTE_STARTED_KEY, False)
global_storage.optimistic_update(CONFIG.SIMPLENOTE_SYNC_TIMES_KEY, 0)


def reload_if_needed():
# global SIMPLENOTE_RELOAD_CALLS

# # Sublime calls this twice for some reason :(
# SIMPLENOTE_RELOAD_CALLS += 1
# logger.warning((SIMPLENOTE_RELOAD_CALLS, SIMPLENOTE_RELOAD_CALLS % 2))
# if SIMPLENOTE_RELOAD_CALLS % 2 != 0:
# logger.debug("Simplenote Reload call %s" % SIMPLENOTE_RELOAD_CALLS)
# return

logger.warning(("CONFIG.SIMPLENOTE_SETTINGS_FILE_PATH", CONFIG.SIMPLENOTE_SETTINGS_FILE_PATH))
settings = sublime.load_settings("Simplenote.sublime-settings")
autostart = settings.get("autostart")
if bool(autostart):
autostart = True
logger.debug(("Simplenote Reloading", autostart))
settings = sublime.load_settings(CONFIG.SIMPLENOTE_SETTINGS_FILE_PATH)
autostart = settings.get("autostart", True)
if not isinstance(autostart, bool):
show_message("`autostart` must be a boolean. Please check settings file.")
return
if autostart:
sublime.set_timeout(start, 2000)
logger.debug("Auto Starting")
start()


def plugin_loaded():
# load_notes()
logger.debug(("Loaded notes number: ", Note.tree.count))

logger.warning(("CONFIG.SIMPLENOTE_SETTINGS_FILE_PATH", CONFIG.SIMPLENOTE_SETTINGS_FILE_PATH))
settings = sublime.load_settings("Simplenote.sublime-settings")
settings = sublime.load_settings(CONFIG.SIMPLENOTE_SETTINGS_FILE_PATH)
# logger.debug(("SETTINGS.__dict__: ", SETTINGS.__dict__))
# logger.debug(("SETTINGS.username: ", SETTINGS.get("username")))

settings.clear_on_change("username")
settings.clear_on_change("password")
settings.add_on_change("username", reload_if_needed)
Expand Down
Loading