Thành viên:Plantaest/Zinnia/Prototype 1 & 2Zinnia là tên của một dự án phần mềm đang được phát triển bởi thành viên Plantaest và cộng đồng. Mục tiêu của Zinnia là một phiên bản tốt hơn cho Thay đổi gần đây và Twinkle. Đăng ký nhận báo cáoKhoảng 1–4 tuần, nếu có các báo cáo quan trọng thì mọi người có thể đăng ký nhận tin (thông báo qua ping), bằng cách ký vào danh sách bên dưới. Các báo cáo sẽ đăng trên trang thảo luận của dự án. Mọi ý kiến góp ý trong quá trình phát triển phần mềm đều được ghi nhận một cách trân trọng.
Lịch sửBối cảnhViệc thực hiện các chức năng quản lý wiki đã và đang được triển khai thông qua một số công cụ kinh điển như RecentChanges (Thay đổi gần đây), RTRC, Navigation popups, Twinkle, Huggle, hay một số công cụ mới hơn như RedWarn/Ultraviolet, SWViewer, AntiVandal. Ngoài ra, còn có sự hỗ trợ từ rất nhiều các user script, những tập lệnh được cộng đồng phát triển theo nhu cầu cá nhân hoặc nhu cầu tập thể, có thể khá đơn giản và chỉ thực hiện một trách nhiệm duy nhất như BlankedThePage. Nhìn chung, hệ thống những công cụ lớn được đề cập ở trên, cùng với các user script, đã có thể giúp quản lý wiki tương đối ổn định; các thao tác như duyệt sửa đổi, lùi sửa, thêm bản mẫu đều khá dễ dàng thực hiện. Tuy nhiên, nếu xét riêng từng trường hợp thì mỗi công cụ đều có những hạn chế riêng của nó:
Tóm lại, mỗi một công cụ đều có những ưu nhược điểm riêng, việc sử dụng kết hợp nhiều công cụ khác nhau (nhất là sử dụng thêm các user script) có thể giúp giảm thiểu các nhược điểm, cũng như đảm bảo trải nghiệm và cảm xúc thoải mái khi làm việc trên wiki. Tháng 7 năm 2022Ý định về việc thực hiện một chương trình tương tự RecentChanges và Twinkle đã được tôi quan tâm từ khá lâu, vì nhận thấy những nhược điểm lớn của hai công cụ kinh điển này. Tuy nhiên, từ trước năm 2022, tôi ít khi làm việc với JavaScript và hầu như không quan tâm nhiều về front-end, vì vậy kiến thức lúc đó là không đủ để triển khai ý tưởng. Tiện ích TwinkleMobile được viết vào cuối năm 2021, có thể nhận thấy là cách viết mã JavaScript lúc đó khá bừa bộn. Từ đầu năm 2022, tôi bắt đầu học tập "tương đối" nghiêm túc JavaScript và một số công nghệ liên quan như TypeScript, React. Đến cuối tháng 7 năm 2022, tôi đã bày tỏ ý định làm một công cụ thay thế cho RecentChanges và Twinkle trên trang thảo luận của thành viên NguoiDungKhongDinhDanh, và đã nhận được một số góp ý khá hợp lý. Tháng 9–10 năm 2022: Prototype đầu tiênCuối tháng 9, đầu tháng 10 năm 2022, tôi mới có thời gian để bắt tay vào việc dựng prototype đầu tiên của dự án. Nếu không nhớ nhầm thì việc này diễn ra trong khoảng 2–3 tuần.
Thời điểm thực hiện prototype đầu tiên này là một khoảng thời gian khá quý báu, khi tôi nhận ra những ý định thiết kế ban đầu khi được trình bày thực tế đã không mang lại lợi ích như dự tính, đó là lý do chính mà prototype này đã bị hủy bỏ, một phần nữa là do lúc đó khá bận công việc cá nhân. Lý giải chi tiết như sau:
Tháng 3 năm 2023: Prototype thứ haiGiữa tháng 3 năm 2023, sau khi đã giải quyết xong xuôi nhiều công việc cá nhân, tôi bắt tay vào việc thực hiện prototype thứ hai, từ một số ý tưởng manh nha sau nhiều tháng liền suy nghĩ, cũng như tái tham khảo một số chương trình tương tự như Huggle, SWViewer, AntiVandal. Tôi bắt đầu lại từ việc xác định ý nghĩa của dự án. Mục tiêu của dự án là xây dựng một phiên bản thay thế có thể tốt hơn cho 2 công cụ RecentChanges và Twinkle, như vậy, khả năng một điểm cạnh tranh quan trọng của nó chính là giao diện người dùng. Đó phải là một giao diện có tính hài hòa và kế thừa, nếu quá tập trung vào những khái niệm lạ lẫm như workspace thì có thể khiến người sử dụng không quen thuộc so với những trải nghiệm từ trước. Xét về RecentChanges, tôi nhận định ý nghĩa của nó là dùng để duyệt một danh sách các thay đổi, và kiểm tra sự khác biệt (diff). Như vậy, yếu tố cốt lõi xuyên suốt trong dự án chính là diff. Đó là thứ phải được thể hiện một cách rõ ràng và tường minh, và cần tập trung nhiều nhất. Vì diff giúp người dùng trực tiếp xác định một sửa đổi là thiện ý hay phá hoại, dù cho một số thông tin khác như con số chênh lệch kích thước văn bản giữa hai phiên bản, thông tin quyền người dùng, hay điểm ORES cũng có thể mang lại hiệu ứng tương tự, nhưng chúng chỉ nên là thông tin bổ sung trong quá trình đánh giá sửa đổi. Prototype thứ haiPrototype này tập trung biểu diễn những thành phần quan trọng nhất của hệ thống, để từ đó có một sự hình dung tương đối về phần mềm trong tương lai, cũng như có cơ sở để thiết kế hệ thống và lập kế hoạch triển khai. Thiết kế tổng thểTừ thực tế khảo sát, các công cụ có biểu diễn "Thay đổi gần đây" đều có 2 dạng chính: (1) gói các thành phần trong một hộp (compact), và (2) dãn theo nội dung (fit-content). Giao diện (1) xuất hiện ở những công cụ như RTRC, Huggle, SWViewer, AntiVandal. Giao diện (2) xuất hiện ở RecentChanges, Raun. Giao diện compact có nhược điểm so với giao diện fit-content là nó giới hạn không gian cuộn của feed "Thay đổi gần đây", thường là sẽ nằm trong một panel góc trái; nhưng ưu điểm là có thể dành được không gian rộng hơn để thể hiện diff. Giao diện chính của Zinnia kế thừa hai giao diện trên, vừa đảm bảo không gian cuộn của feed "Thay đổi gần đây" rộng nhất có thể (do không đóng gói), nhưng cũng dành được không gian lớn cho diff (đính kèm panel chứa diff theo thao tác cuộn). Giao diện chính của chương trình gồm có 3 panel chính: FeedPanel, TabPanel, và ControlPanel. Ngoài ra, còn có một panel phụ ở đầu là HeaderPanel để thể hiện thông tin dự án. FeedPanel gồm các FeedItemCard xếp theo chiều dọc, không gian cuộn của FeedPanel là toàn màn hình.
HeaderPanelHeaderPanel là panel phụ chứa thông tin về phần mềm, bao gồm logo, slogan, một số liên kết đến các trang ngoài. Nó xuất hiện ngay khi mở chương trình, sau màn hình splash. HeaderPanel được ẩn đi khi người dùng cuộn xuống.
Không gian làm việc chínhMàn hình làm việc là sự kết hợp của 3 panel chính theo chiều từ trái qua phải: FeedPanel, TabPanel, ControlPanel. Trong đó, FeedPanel là panel chứa feed, thể hiện dưới dạng các card gọi là FeedItemCard. TabPanel là panel thể hiện nội dung của một tab và các thành phần chức năng có liên quan, trong ví dụ hiện tại thì nó là DiffTabPanel, dùng để thể hiện một diff. ControlPanel là nơi chứa các nút điều khiển chính của chương trình.
FeedPanelFeedPanel là nơi chứa feed, thể hiện dưới dạng một stack gồm các FeedItemCard. FeedItemCard gồm các thông tin của một feed item, là một đối tượng chung được thể hiện cụ thể tùy bối cảnh. Nếu là feed Recent Changes và Watchlist thì feed item là "change"; feed New Pages là "page"; và feed New Files là "file". Trong ví dụ, feed item là một change, cụ thể là "edit change" (sửa đổi), nên sẽ có những thông tin điển hình như thời điểm sửa đổi, điểm ORES, con số chênh lệch kích thước văn bản, trang được sửa, thành viên sửa, và wiki. Có thể bổ sung thêm một số chỉ báo (indicator) để thể hiện thêm một số thông tin, nhưng cần cân nhắc để giữ FeedItemCard cân đối. Đối với FeedItemCard của edit change, khi hover sẽ xuất hiện một hovercard chứa 3 nút: [Diff], [New tab], [See later]. [Diff] là nút khi hover thì hiển thị một hovercard để xem trước diff của sửa đổi (DiffPreviewHovercard). [New tab] khi bấm vào thì edit change được mở trong một tab mới. [See later] khi bấm vào thì edit change được thêm vào bộ sưu tập See later (Xem sau).
TabPanel và DiffTabPanelTabPanel là nơi chứa nội dung của tab và một số chức năng có liên quan. DiffTabPanel là trường hợp TabPanel thể hiện một diff (đến từ đối tượng change của feed). DiffTabPanel có 3 phần theo chiều từ trên xuống:
ControlPanelControlPanel là nơi chứa các thành phần điều khiển chính của chương trình, bố trí trong một panel hẹp theo chiều từ trên xuống. Gồm có các thành phần sau: FeedsMenuFeedsMenu là một action icon. Khi hover thì hiện một hovercard là FeedsHovercard, cho phép chuyển qua lại giữa các feed của workspace. Khi bấm vào thì hiện một modal là FeedsModal, chức năng tương tự FeedsHovercard, thuận tiện cho giao diện di động (do hovercard bị tắt).
[Previous] và [Next][Previous] và [Next] là hai nút để điều hướng feed, cho phép di chuyển lên hoặc xuống feed item kế trước hoặc kế tiếp. FiltersMenuFiltersMenu là một action icon. Khi hover thì hiện FiltersHovercard, cho phép chuyển qua lại giữa các filter của feed. Khi bấm vào thì hiện FiltersModal, để cài đặt chi tiết các filter của feed.
PageHistoryCarouselPageHistoryCarousel là một carousel thể hiện lịch sử của trang gắn với tab đang mở. Nó xuất hiện tùy vào từng loại tab, ví dụ nếu là một tab Welcome (Chào mừng) thì nó không hiển thị trên ControlPanel.
TabsMenuTabsMenu là một action icon. Khi hover thì hiện TabsHovercard, cho phép chuyển qua lại giữa các tab. Khi bấm vào thì hiện TabsModal, cho phép chuyển tab, xóa tab.
WorkspacesMenuWorkspacesMenu là một action icon. Khi hover thì hiện WorkspacesHovercard, cho phép chuyển qua lại giữa các workspace. Khi bấm vào thì hiện WorkspacesModal, cho phép chuyển qua lại workspace, mở một số modal khác để xem chi tiết, sửa, xóa workspace bằng một menu ẩn.
SettingsMenuSettingsMenu là một action icon. Khi hover thì hiện QuickSettingsHovercard, để thực hiện nhanh một số thiết lập, như bật tắt chế độ tối của giao diện. Khi bấm vào thì hiện SettingsModal, để thực hiện các thiết lập cho chương trình.
MiscMenuMiscMenu là một action icon, khi hover thì hiện MiscHovercard, chứa các nút dẫn đến các chức năng khác của hệ thống. Theo ví dụ hiện tại thì có 3 nút: [See later], [Logs], [About]. Khi bấm vào mỗi nút trên thì hiện ra một modal chứa thông tin liên quan đến chức năng tương ứng.
GlassPanelGlassPanel là một yếu tố thiết kế, được thể hiện dưới dạng mặt gương mờ (sử dụng Kiến trúc tổng thểTừ thiết kế của prototype thứ hai, chương trình có thể có kiến trúc dự kiến như sau:
Những moduleCoreZinnia Core là module chính của chương trình. Nó là hiện thực của những khái niệm chính trong kiến trúc tổng thể, bao gồm: workspace, feed, filter, tab, see later, v.v. Sự thực hiện đó chính là việc biểu diễn các khái niệm kiến trúc thành những đối tượng đồ họa của giao diện người dùng, cũng như triển khai các chức năng cho giao diện đó. Ví dụ, feed được biểu diễn dưới dạng một stack [panel] gồm nhiều feed item [card], và có chức năng hiển thị chính xác nội dung feed theo dữ liệu được cung cấp từ API. Core cũng là đầu mối giúp người dùng tương tác với các module khác của hệ thống. Ví dụ, trong các tab, Core cung cấp các tool của module Toolbox theo bối cảnh nội dung của tab, điển hình như khi truy cập diff tab, thì Core cung cấp tool "Mark as patrolled", là một nút bấm đơn giản để người dùng có thể dùng cho việc đánh dấu một sửa đổi là "đã tuần tra". MWZinnia MW là module nền tảng của chương trình, nó không có giao diện, và có ý nghĩa là một thư viện để kết nối đến hệ thống API của MediaWiki. Zinnia sẽ không sử dụng trực tiếp đối tượng Hiện tại chưa có thiết kế rõ ràng cho Zinnia MW, nhưng có thể nó là một abstract class:
ToolboxZinnia Toolbox là module quản lý hệ thống tool của chương trình. Tool ở đây là một khái niệm dùng để chỉ những phần chức năng mở rộng được tích hợp vào hệ thống một cách quy ước (theo ý muốn của hệ thống) hoặc tự do (theo ý muốn của người dùng). Zinnia Toolbox Framework (ZTF) là một thư viện nền tảng hỗ trợ triển khai các tool cho hệ thống, cung cấp sẵn một số giải pháp để giải quyết các nghiệp vụ thường xuyên xuất hiện trong các tool, nó phụ thuộc vào module Zinnia MW. Ví dụ, ZTF có thể có hàm Ý định ban đầu thì Toolbox sẽ bao gồm các tool tương tự Twinkle, như vậy sẽ có các tool điển hình như: Fluff, Speedy, Warn, Tag, ARV, Welcome, Image, PROD, XFD, Talkback, SharedIP, BatchDelete, BatchUndelete, Protect, BatchProtect, Block, DePROD, Unlink. Để tránh lặp lại sai lầm trong 2 vấn đề i18n là l10n của Twinkle, các tool của Zinnia sẽ giải quyết 2 vấn đề này như sau:
Tool của Zinnia có thể có 2 loại: native và sandboxed. Native tool là những tool được thiết kế và xây dựng trên nền tảng của Zinnia, nó sở hữu một giao diện người dùng có tính liên hợp với giao diện chính của chương trình. Điều này tạo ra sự đồng bộ giao diện và đảm bảo trải nghiệm người dùng được thông suốt. Những tool được đề cập ở trên (lấy nguyên mẫu từ Twinkle) đều là các native tool. Sandboxed tool là những tool có bản chất là một user script được đóng gói trong một sandbox. Sự tồn tại của sandboxed tool là do hệ thống user script khá hữu ích, nếu có thể tận dụng lại thì sẽ giải quyết được khá nhiều vấn đề mà không cần phải tốn công viết mới các native tool. Nhược điểm của sandboxed tool là nó không thể liên hợp về mặt giao diện, cũng như có thể gặp vấn đề về việc i18n và l10n. Về định hướng triển khai thì tham khảo đề mục của module Sandbox. SandboxZinnia Sandbox là một module hỗ trợ đóng gói các user script hiện có của cộng đồng trong một môi trường tách biệt để có thể sử dụng và tương tác một cách an toàn trong hệ thống Zinnia. Hiện tại chưa có một thiết kế rõ ràng cho module này. Công cụ hỗ trợ xây dựng Sandbox có thể là thư viện websandbox của JetBrains. Về mặt kỹ thuật, việc sandbox hóa một user script có thể là một công việc khá tốn kém, do phải xử lý kỹ các side effect. User script có thể cần truy cập các đối tượng global điển hình như Module Sandbox tạo ra các sandboxed tool từ các user script, và những sandboxed tool này có thể tương tác ngược lại môi trường Zinnia thông qua một số API, điều này cần được thảo luận thêm. Một hệ quả khá thú vị là những công cụ của Twinkle có thể chạy được trên Zinnia thông qua module Sandbox. Điều này khá hữu ích vì thời gian đầu chắc chắn không thể triển khai được hết các native tool lấy nguyên mẫu từ Twinkle, nên việc có sẵn các công cụ của Twinkle sẽ giúp người dùng tiếp tục các trải nghiệm thường ngày mà không bị gián đoạn khi sử dụng Zinnia. IndexZinnia Index là một chỉ mục cho biết những user script nào đã được sandbox hóa thành công và có thể sử dụng được trong chương trình. Người dùng có thể thêm các sandboxed tool từ danh sách Zinnia Index, việc này khá giống như khi tải ứng dụng từ một chợ. Chỉ mục này chỉ có ý nghĩa xác nhận sự tương thích. Người dùng có thể tự do tạo các sandboxed tool từ các user script có sẵn thông qua một giao diện, nhưng việc này có thể cần có kiến thức lập trình nếu như gặp trường hợp cần thiết lập config cho module Sandbox. Ngoài ra, việc thêm thủ công như vậy cũng không thể chia sẻ sandboxed tool cho những người dùng khác. Như vậy, việc có một chỉ mục như Zinnia Index là khá cần thiết. Công nghệ sử dụngZinnia là một ứng dụng front-end, khả năng cao là nó không cần back-end, do chỉ tương tác với API của MediaWiki, và chạy trên môi trường front-end cũng của MediaWiki. Các tập lệnh của chương trình sẽ được trữ trên một máy chủ Toolforge, nó không được trữ trên trang thành viên wiki (ngoại trừ một script nhỏ để kết nối với máy chủ Toolforge), nguyên nhân là do bundle size có thể rất lớn nếu dồn hết các module, tool vào một file duy nhất; giải pháp là chia ra các ES Module và dùng kỹ thuật lazy load của React. Phía ReactReactReact là nền tảng chính để triển khai dự án. Nếu dự án này mà dùng Vanilla JavaScript hay jQuery thì chắc chắn không thể làm nổi. TypeScriptTypeScript là ngôn ngữ chính của dự án. MantineMantine là thư viện chính để xây dựng giao diện cho dự án. Nhiều người hay nhiều hướng dẫn nói nên dùng Material UI (MUI) hay Ant Design (antd), nhưng thật sự các thư viện này khá thừa và đôi khi lại thiếu (thu phí linh tinh). TanStack QueryTanStack Query là thư viện giúp quản lý server state. Nó giúp đơn giản hóa quy trình tương tác với API, như vậy khả năng cao nó sẽ bọc các hàm của module Zinnia MW, vì các hàm này là các hàm async thô (trả về Promise của JavaScript hoặc Promise của jQuery, đều có tính thenable). JotaiJotai là thư viện giúp quản lý client state. Nguyên nhân cho việc lựa chọn thư viện này thật sự không rõ ràng, nhưng có thể là nó khá đơn giản và dễ hiểu, và tôi cũng không thích kiểu selector function của Redux hay Zustand. Nhóm pmndrs còn có thư viện Valtio để quản lý client state ngoài hai thư viện Jotai và Zustand, nhưng nó dùng proxy, tương tự Pinia của Vue. Proxy là thứ khá nguy hiểm nên tốt nhất không nên đụng. ViteVite là môi trường phát triển chính của dự án, nhìn chung có vẻ nó thực hiện hot reload nhanh hơn Webpack, và đồng thời build cũng tiện hơn nhờ tích hợp Rollup. Khác
Phía MediaWikiNhìn chung sẽ tái sử dụng nhiều công nghệ được cung cấp bởi MediaWiki, như các module của ResourceLoader (bao gồm MediaWikiJS Core, OOjs, OOUI, jQuery), các editor (bao gồm WikiEditor, VisualEditor, 2017 wikitext editor, CodeEditor), các công cụ hữu ích khác như DiscussionTools. Chủ yếu vì lý do tương thích và đỡ mất công viết mới, dù việc tích hợp với phía React có thể gặp một số vấn đề. Ngoài ra, cũng có sử dụng một số thư viện liên quan đến wiki do cộng đồng cung cấp, như mwn, types-mediawiki. Chủ yếu để có type, không bị TypeScript báo lỗi. Các thảo luận khácVấn đề chạy tool của Zinnia ngoài Special:BlankPage/ZinniaCác tool của Zinnia có thể được chạy ngoài môi trường sử dụng chính là Special:BlankPage/Zinnia. Ví dụ, nó có thể xuất hiện dưới dạng một dock ở một trang diff của wiki. Vấn đề chạy Zinnia ngoài môi trường front-end của MediaWikiZinnia có thể chạy trên một server riêng, cần sử dụng class Nhật ký triển khaiTháng 3 năm 2023
|