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

Akira File Format #90

Open
2 of 5 tasks
Alecaddd opened this issue Feb 27, 2019 · 25 comments
Open
2 of 5 tasks

Akira File Format #90

Alecaddd opened this issue Feb 27, 2019 · 25 comments
Milestone

Comments

@Alecaddd
Copy link
Member

Alecaddd commented Feb 27, 2019

This is a behemoth and we will probably split this issue into multiple sub-tasks, but let's start collecting our approach here.

  • Save and Open design file with .akira format.
  • The file is a zip archive with an svg file and a hidden .git repository
  • The file needs to generate a thumbnail to preview the currently saved design
  • At every save triggered command, a new commit should be pushed to the local git repo
  • Ability to visualize the commit history and revert back to a previously saved state

I'm still not sure if we should deal with undos the same way, or keep a limited amount of undos in memory as any other application.

@Alecaddd Alecaddd added this to the v1.0 milestone Feb 27, 2019
@Alecaddd Alecaddd added this to To do in FIle manager via automation Feb 27, 2019
@e200
Copy link

e200 commented Feb 27, 2019

Did you think about use .akr as extension too? I think that how more short, more better.

@ghost
Copy link

ghost commented Feb 27, 2019

Does this mean that Akira will have a dependency on git being installed on the system? Or do you intend to ship a lightweight git implementation with Akira and use that?

@albfan
Copy link
Collaborator

albfan commented Feb 27, 2019

@terndrup in that case, we will use libgit2 so no need for git to be installed

@julientaq
Copy link

if there is some git thing running behind as a save you may end up with very heavy file (especially with one svg with everything inside). Maybe having a keep this version action that the user can trigger would be more efficient that saving every change with git. but i see where you're going 👍

Also, the idea of having git behind could be pretty useful to merge (got already some UX idea about how it could be done :D) or to fork a project. be sure that these options don’t get forbidden by your git implementations please :D.

@Alecaddd
Copy link
Member Author

@julientaq since we're managing everything via SVG, which is basically just an XML string, we should be able to keep the file size quite low.
We'll need to test it anyway and see if it gets out of hand.
An option to delete older versions is being considered, also, to clear the git history and free up some space.

If you want to contribute with some design ideas, we'll need a popup window where you can scroll through the commits (probably named with the date and time) and the preview image for that commit.
A sort of time machine like experience in MacOs.

timemachine

@snowparrot
Copy link

You should consider other free alternatives to zip as the algorithm is very outdated (from the 80s)

A good alternative:
https://en.wikipedia.org/wiki/7z

Also free and open.

@Jab2870
Copy link

Jab2870 commented Mar 5, 2019

Despite the primary format being SVGs, presumably bitmap images are going to be supported in Krita? If so, these will make the file size big, GIT was never really designed to manage binary files. One option might be to look at GIT LFS although I don't know how it would work with libgit2.

Another thought, if this is basically a git repo, would it be possible to manage it manually? If, as well as a .akira zip file, I would love to be able to open it from an uncompressed directory that I manually manage with git.

Lastly, will you facilitate the ability to push the git repository to a remote repository? Obviousl, if we are able to facilitate managing the repo manually, this would be addressed by that.

@jhrdina
Copy link

jhrdina commented Mar 11, 2019

😄 If you really want to be future-proof and maybe want to support real-time online collaboration in a distant future (with independent offline edits and seamless conflict resolution, without a necessary need for central server), you might want to consider designing your JSON files and document representation as CRDTs (conflict-free replicated data types) and replace Git this way.

CRDTs naturally keep track of document state history, but at the same time allow you to specify automatic merging semantics for different subtrees of the JSON for the case of concurrent edits (Example for a list of shapes: You have a rectangle A, one offline user removes it, second offline user changes its dimensions. What happens after online sync? You can specify e.g. that list of shapes should have UPDATE WINS semantics, so that the rectangle gets "unremoved" and the dimensions change (update op.) doesn't get lost.) CRDTs design ensures that after sync everybody ends up with the same document state (usually formally proven).

There are interesting implementations in JavaScript, e.g.:

  • based on δ-CRDTs (delta state CRDTs, a popular variant of CRDTs): ipfs-shipyard/js-delta-crdts
  • or some other approach (here with predefined merging semantics, but on the other hand with infinite nesting support - not sure you really need this): automerge/automerge

I'm not sure how many native CRDTs implementations are there and yes, reimplementing custom library would require some time...

The thing is (in my opinion) it might be hard to add collaboration support into an offline-only app down-the-line, when your data-structures and file-format are already defined and are not designed for collaboration. (See Sketch - it still doesn't support real-time collaboration, does it? I don't have a macOS on hand, sorry...)

I hope I didn't disturb you too much! 😄 You know... I had to mention CRDTs, it is the new medicine that cures every problem, right? 😄 I really keep my fingers crossed for your project, I absolutely understand that you have some limited resources, but still, at least for the record, I had to mention this technology. 🙂

@gdelazzari
Copy link

The main issue I would have with the .akira file being a ZIP archive (or whatever kind of non-text file) is that versioning that would be an issue. I mean it's not that it won't work, but I usually make one Git repository for a project (unless it's a really big one) and have everything in there, from the (Akira) design files to notes to code, documentation, etc... It doesn't make any sense for such a use case to have the design file being an archived git repo inside another git repository. A lot of space would be wasted since the outer repo wouldn't be able to manage the internal one efficiently. This gets worse with every Akira file that is inside (I can see having multiple designs on a single repo).

I'm not sure what the best option would be.

If a user wants to store the Akira file inside a repository, the file should just represent the design with a text format (even SVG is totally fine). For users which won't store the file inside a repo, then something like what @jhrdina described seems really cool. Not sure about having that inside a repo, history would be duplicated anyway...

This doesn't seem to be a straightforward issue to solve. Assuming that my use case is shared by other people of course (i.e. if I'm the only one then who cares 😄 ).

The best solution I can think of is to have 2 formats ("raw" SVG without versioning and something specific with versioning) and make the user choose or choose automatically (i.e. when saving for the first time, traverse the directories and if a VCS repository is found then save in SVG (after asking the user for confirmation) otherwise use the versioned format.

Just sharing my two cents, hope it's appreciated

@Alecaddd
Copy link
Member Author

Alecaddd commented Apr 8, 2019

Thank you all for your insightful suggestions and point of views.
We started working on this implementation and you can take a look at the initial work done on this PR: #110

@jhrdina you're not disturbing us at all, on the contrary, we need these suggestions since day 1 in order to avoid conflicts or technical issues while trying to implement new features in the future.
Would you be able to prototype a quick example, even not fully functional, to adopt CRDTs on the PR made by @Philip-Scott?

@gdelazzari thanks for your suggestion as well.
I personally don't see the problem as the .akira file is meant to be a standalone GIT repo itself to keep the full history of your design while shared across computers and users.

The idea here is to offer built-in version control for designers who have no idea what GIT is.
It's great that you know how to set up a repo and use your own version control system, but the majority of the users don't.

Offering a version control already into one single file out of the box is convenient and removes any technical barrier. The user can upload that single file on a cloud storage for backup, knowing that one file contains the full history and versions of the project.

You can save that file on a remote GIT repo as well if you want, but that seems quiet an overkill as you won't need to keep a history of versions of that file.

If in your case you decide to not use the built-in version control of Akira, you can simply export your design in SVG and set up your own repo.

@gdelazzari
Copy link

Thanks for the response and the clarification, I take for granted that you have a way better understanding of Akira's users needs than me, since I'm not a designer myself. In that case the .akira file format sounds good. CRDTs seem to be a really interesting thing though, hope you can do some testing with such a technology and evaluate them.

The user can upload that single file on a cloud storage for backup, knowing that one file contains the full history and versions of the project.

Not so relevant, but just to be complete ("mettere i puntini sulle i") it's also true that most cloud services already do version control by themselves. I don't think someone would want to disable Akira's built-in versioning because their favorite cloud storage already versions the files, but it's also to realize that (IMHO) we're going more and more into versioned file storage services/systems. Again, not so relevant, but still worth to consider in order to "see the thing in its entirety", I think.

Regarding the versioning inside the .akira files, I honestly don't think Git is a great idea. I mean, of course it's freaking battle-tested and everything, but is such a complex and full-featured system really needed? Also, how easy is it to make it manage the repository inside the archive? Does libgit provide user-definable hooks for opening, reading, writing, etc.. files so that they can be overridden with functions that operate inside the archive?

I think something ad-hoc could be implemented, since the file format has a relatively simple and known structure which should make it less harder.

CRDTs seem indeed the best solution IMHO, also being future-proof for (real-time) collaboration or whatever.

Again, just my two cents 🙂

@jhrdina
Copy link

jhrdina commented Apr 8, 2019

Would you be able to prototype a quick example, even not fully functional, to adopt CRDTs on the PR made by @Philip-Scott?

I wish I had the time... unfortunately, I'm currently desperately busy with with my Master's Thesis and eventually finishing my Master's Degree. I don't think I will able to help with coding before the end of June. 😒

The general approach would be not to save the final document (graphical objects in your case), but rather single operations/deltas that lead to creation of the document (add rectangle to pos XY, move object with UUID af1b11234 to pos X'Y', remove object with UUID 197dff). These operations then get "replayed" on each file opening to get the current (or older) version of the document. Using these discrete operations, CRDTs can find out a lot about different user's actual intents and therefore can offer much better conflict resolution (in contrast to comparing two static finished documents).

I've found a C++ reference implementation of δ-CRDTs:
https://github.com/CBaquero/delta-enabled-crdts

The Automerge JS library mentioned above doesn't allow you to exactly specify the merging semantics, it does, on the other hand, offer some interesting advanced features - undo/redo support, relational JSON tables, optimized collaborative text editing... The underlying implementation might be a bit harder to port, because it uses JavaScript Proxies to "record" changes and also builds upon Immutable datatypes - these are great, as they enable structural sharing (you can have multiple snapshots of a document in time and share data that didn't change between snapshots) - the problem is I don't know any immutable data-structures implementation for Vala.

You can however play with the library in codesandbox, I've created, so that you can get the feeling of dev experience I would hope for. If you uncomment the last line, you can see in the console all the generated operations ready to be saved to file. You can also dig into CRDT internals using DevTools.

This is probably all I can do for you right now... :/

@Jab2870
Copy link

Jab2870 commented Apr 9, 2019

I think part of the problem might be mitigated if we have the ability not to "zip up" the file at the end. This would allow anyone with an existing understanding of git to use the akira directory as a sumodule rather than a binary file that cannot easily/efficiently be version controlled in part of a larger repository.

@Alecaddd
Copy link
Member Author

Alecaddd commented Apr 9, 2019

I'm sorry guys but I completely disagree with where this is going. I think the main fact is that I wasn't able to properly communicate the purpose and the implementation of this feature, so, I will try again.

First of all, giving the option to save in one way or another, or manually manage the repo, or do other things other than "Click > Save", would be a nightmare. It'd add so much complexity to the code only to support few edge cases.

The fact that you read the word "GIT" doesn't mean you will even know there's a GIT repository in your Akira file. It shouldn't be of your concern.
The built-in GIT repo is for the application itself to keep track of different versions every time a user saves the file.
Save Action -> new commit
Edit, Save -> another commit
...

Since we're parsing the entire canvas with every single object in a JSON format, we're storing the entire design as text. Images and other assets will be stored inside dedicated folders within the .akira file itself.
We will offer no support whatsoever in opening the akira file as a regular archive as this will be managed by the entire application.

In within Akira, you will be able to visually see the history of your commits (which will not be called commits), and visually see the differences between various saved states. You will be able to see the saved assets, delete them, as well as clear your history from a point in time of your choice.

All of this will be handled by a properly defined UI, inside the app itself, removing the necessity of handling these stuff manually with a custom repository.
The non technical users will not even know that a GIT repo is used to do this.

If someone doesn't want to use the built-in version control (we should probably call it something else), he will be able to deactivate it from the UI, but the saved file will always be the .akira archive, because of all the other assets and resources we need to store.

Once again, if you guys want to use your own Git repo for whatever reason, you can simply export your design in SVG and commit that file, but this process will not be managed by Akira.

I hope this will clear a bit the issue and will help to understand the purpose and objective of this implementation.

@Alecaddd
Copy link
Member Author

Alecaddd commented Apr 9, 2019

With that said, in the future, we have the plan to implement a remote cloud sync option, which will allow the user to use our own cloud VPS, or connect it to their own.
But still, we need the app and our code to manage every single step. If we allow users to "make their own thing" or use it the way they want, we will have so many issues and bug reports that it will be impossible to cover every single use case.
It's a matter of mental sanity, scalability, and maintainability.

@gdelazzari
Copy link

gdelazzari commented Apr 9, 2019

Uhm, not sure if you was also referring to my last comment or not, if you were I think there was a bit of a misunderstanding.

As I said, the path you're taking looks fine IMHO (even if that would mean more work for people like me that uses Git or whatever).

I was just trying to give a suggestion from a development/technical point of view.

The .akira file contains assets, the JSON representation of the design and whatever you have in mind, but I was simply suggesting to look into something else than Git inside the archive to accomplish file versioning, since

I honestly don't think Git is a great idea. I mean, of course it's freaking battle-tested and everything, but is such a complex and full-featured system really needed? Also, how easy is it to make it manage the repository inside the archive? Does libgit provide user-definable hooks for opening, reading, writing, etc.. files so that they can be overridden with functions that operate inside the archive?

With "how easy is it to make it manage the repository inside the archive" I meant "how easy is it to use libgit in Vala to make it work with the .git directory inside the archive", I was not referring to the user managing the Git repository inside the .akira archive.

So my suggestion was to look into a simpler alternative, which could simply be to bring in (or implement - if no one has ever done that in Vala) just a text-diff algorithm (instead of the relatively huge Git system) and store the the diff for each file save/change inside the archive. Given the suggestion of CRDTs, looking into them could be an even better option at this point.

I hope that it's now clear what I meant and you can evaluate this suggestion. It's just easier IMHO from a development perspective. You'll have to bind to a C library anyway, why bind to the entirety of libgit if you just need to preserve history? Just bind to a C text diffing library, the binary will be way smaller and it simply makes more sense to me, I mean bringing in Git with branches, remote capabilities, merging algorithms, etc.. doesn't make sense.

@Alecaddd
Copy link
Member Author

Alecaddd commented Apr 9, 2019

With "how easy is it to make it manage the repository inside the archive" I meant "how easy is it to use libgit in Vala to make it work with the .git directory inside the archive", I was not referring to the user managing the Git repository inside the .akira archive.

Vala offers native bindings for libgit2 https://valadoc.org/libgit2-glib-1.0/Ggit.html

My message was mostly directed to stop the discussion of "Having the option to manage the GIT archive the way we(users) want", not regarding your valid suggestions 😄

So my suggestion was to look into a simpler alternative, which could simply be to bring in (or implement - if no one has ever done that in Vala) just a text-diff algorithm (instead of the relatively huge Git system) and store the the diff for each file save/change inside the archive.

Using libgit2 will not mean we have to install Git locally inside Akira. That's not necessary.

You'll have to bind to a C library anyway, why bind to the entirety of libgit if you just need to preserve history?

Because this is only the first step.
Using GIT brings many pros:

  • A solid and battle-tested system (as you said).
  • A system that works everywhere, in every distro, and environment.
  • A system that it's well known and allows everyone to contribute without learning something we built from scratch.
  • A system that offers way more than we need right now, and allows us to evolve with time, implement new features, and scale our built-in version control way faster than using a custom solution.

Using GIT may seem an overkill for the simple system we want to ship with v1, but it's a necessity to future proof our app and allow us to implement new feature without rebuilding the save system once a year.

I mean bringing in Git with branches, remote capabilities, merging algorithms, etc.. doesn't make sense.

It doesn't make sense now, but the goal of Akira is to offer a complete design system platform capable of following design iterations in a sane way. We want to implement in the future some crazy options that will boost productivity 10x:

  • Save a snapshot of your design before doing some edits (branch out)
  • Cloud sync your design (remote git repo)
  • Design collaboration and shared assets between design iterations (merging algorithms)

Cheers

@gdelazzari
Copy link

Clear enough, sounds very good 😎

So to use libgit2 I assume Akira will have to keep the currently opened .akira file "unpacked" in some temporary directory to make libgit work? After taking a first glance at the documentation it seems it's only possible to work with a Repository that's on a "physical" file path, i.e. there's no way to override libgit2 file read/write methods to make them work directly on the archive, right?

I'm bringing this up just to understand if this way of working on the currently opened file would have any drawbacks to tackle, such as...

what happens if the application crashes or is closed unexpectedly before the contents of the temporary directory are archived in the .akira file? I assume you'll want to update the .akira archive every time there has been a change (i.e. every time the user saves the file/"commits" a change) to minimize this risk. Are you looking into some kind of incremental archival of just the changes in the temporary directory or are you planning to rebuild the entire archive each time? In that case it may be a bit problematic if a lot of external assets are imported by the user (let's say on the order of some hundred MBytes) and every time the file is saved the data needs to be archived (potentially compressed) again.

Do you already have some ideas?

(note: I'm not here trying to find weaknesses in the way you want to proceed at all, I just want to share my thoughts to ensure the method that is being chosen will perform well and be reliable, as long as we're in time before it stabilizes 😄 , I hope that's appreciated and I'm not disturbing in any way)

@Philip-Scott
Copy link
Member

@gdelazzari, yes, libgit2 currently only works on physical paths, and we also don't want to hold the whole file in memory since the files can get big. #110 had the initial work to zip and unzip the archive into a hidden folder inside the directory. This way, we can run the git commands, and access files without having to hold it all in memory. Updating the .akira file could be done on closing or saving of the file, with the smaller incremental updates being written to the unarchived dir. That way, if akira were to crash the unarchived contents would still be there and could be restored

@TheAifam5
Copy link

TheAifam5 commented Jul 21, 2019

@Philip-Scott libgit2 supports backends like memcached, mysql, redis, sqlite and you can implement your own too. https://git-scm.com/book/it/v2/Appendix-B%3A-Embedding-Git-in-your-Applications-Libgit2

You can check that project: https://github.com/libgit2/rugged which allows to create a repository in-memory.

The idea putting that case in RAM can be destructive and memory hungry :)

IMO creating an incremental file format (with version, or something to identify for the migration process) would be much safer as Akira will grow up. You need to think about backwards compatibility with older formats, it's hard to define only one file format and use it forever.

Making a 7z or ZIP or other format IMHO is the fastest way but the ugliest.

@albfan
Copy link
Collaborator

albfan commented Oct 9, 2019

Meanwhile we decide how to turn goo canvas into xml (svg) we can play around with serialization

https://developer.gnome.org/json-glib/stable/json-glib-GObject-Serialization.html

We cannot loose any other paint in Akira:

first-draw-akira-ever

Credits to @AUNaseef https://twitter.com/AUNaseef/status/1181771257206857728

@AUNaseef
Copy link

AUNaseef commented Oct 9, 2019

I'd love to see a save feature on Akira soon. Akira is a really powerful tool, its simple interface is much easier to work with as I can just focus on what I am designing. With a save feature, more people will start designing stuff with Akira and I believe it'll help the development of the program.

image
I loved making this one, thought you guys would like to see it | Link to Tweet

We cannot loose any other paint in Akira

Lost one more right there 👆 ;)

@KeizerDev
Copy link

Just from a design/developer perspective who likes to keep things organized in repositories. How would something like this work out if you put your Akira files in a git repository itself? Because if you are planning to use something like a zip format or any other compression mechanism it would not be able to merge.

Maybe it's a good idea to look to how https://github.com/kactus-io/kactus/, Abstract or other solutions solve this.

Ps. I was really looking for something like this for a long time. Almost wanted to switch to Mac os just for Sketch because there wasn't any similar program providing the same simplicity. So keep up the good work!

@albfan
Copy link
Collaborator

albfan commented Oct 15, 2019

@KeizerDev I went through kacktus.io and didn't find really what is there for us. I'm maintainer of gitg and it can compare images in many different ways.

Right now the only real file implementation is a JSON file, so it shouldn't be hard to diff it. In the worst case we will provide a diff filter so git knows how to compare an .akira file.

I need to reread our original file format design an refactor the JSON serialization.

@Alecaddd Alecaddd modified the milestones: v0.0.1, v0.1.0 Jul 12, 2020
@abienz
Copy link

abienz commented Apr 1, 2021

I just recently read about SQLite being used as an application file format, and I wondered if it would be a good fit for Akira's use case.

More information here: https://sqlite.org/aff_short.html

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
FIle manager
  
To do
Development

No branches or pull requests