Full Sail University에서 Final Project로 진행한 복분자막걸리(Raspberry Rice Wine, RRW) 개발 과정에서 작성한 글입니다.
It's the last week(officially, at least) for the coding portion of the project! Therefore I tried to implement features that are very important in the whole workflow: project-level file workflow and a native application menu for macOS.
I started with the application menu. The most challenging point of implementing the menu was communication between the main process and the renderer process. Because the application menu should be made from the main process, it was impossible to use vue-i18n
to localize the application menus, since it relies on Vue 3's Composition API which runs on the renderer process. Therefore I added a new i18n library: i18next
. I just reused the same localization file and setting all the things up wasn't that hard.
However, the next process also required some IPC. Since I should keep the handmade toolbar, which is a Vue component, for platforms other than macOS, it was essential to do some kind of IPC to trigger toolbar actions. I have decided to do this by adding handlers to the renderer side and then sending 'toolbar'
events from the main process to the renderer process. Handlers were unified by assigning IDs for each of the toolbar actions and then mapping them to the toolbar items. While I have also had a problem showing the active route in the native menu, it got solved by sending the route update info and then updating the checked
property of the MenuItem
s.
After finishing the native menu stuff, I have started working on the file workflow. The two most annoying parts of the feature were handling object references and prototypes. Let's start with the problem with object references. Object references to templates are used in layers to map the layers to templates for rendering purposes. However, it wasn't possible to just put the object as a JSON in the output file: it will be a separate object and will break all the stuff. To solve this, I made an ID for each of the templates and then saved it instead of the actual object. After adding some code in the loading phase, the problem got solved and started to work.
The second problem was a bit more annoying: the prototypes. While encoding and decoding an object using JSON, the prototype goes away, which drops all the methods bound to that prototype. In this case, the Color
type was the problem. I solved this by serializing the type to a specific kind of object: TypedObject
. It stores the type name, and the rest of the fields are stored inside the object. It's also typed using the Union Types feature from TypeScript, using the type name as the key for distinguishing the concrete type. The rebuilding process was simple enough to implement: just check the type name and run the conversion method of the type. In the end, it became possible to save and load projects without any data loss.
I'm very proud of the project. I did lots of tasks and have learned a lot of things during the project. I'll try to keep the project alive even after the class by making this project an OSS. I hope to make the app much powerful, and want to see other people using the app happily!