GithubHelp home page GithubHelp logo

cjquines / qboard Goto Github PK

View Code? Open in Web Editor NEW
80.0 1.0 7.0 3.41 MB

The efficient digital whiteboard.

Home Page: https://cjquines.com/qboard/

License: MIT License

JavaScript 4.45% HTML 0.66% TypeScript 87.04% SCSS 7.55% Dockerfile 0.30%
whiteboard

qboard's People

Contributors

cjquines avatar lint-action avatar philipwhiteside avatar pihart avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

qboard's Issues

Demo is not working

Hey, I've been using your demo for a short while, but since last week it's not been working. I then tried to build this into a Linux container that I could run locally and remove dependence from your demo. However, I have not built a node/react app before. I am comfortable with containers/docker, Linux, etc. The Docker config I do create I will share back to this project.

Would you be willing to share the deploy steps to stand this up, and I will work on packaging that into a Linux container.

add collaboration

  • make history pure(-ish)
  • add server (with the option of being headless)
  • emit serialized history to server
  • reproduce from history
  • add spectating to frontend
  • deal with getNextId concurrency issues
  • add collaboration to frontend
  • test for editing concurrency issues

Update documentation

  • Save and export switch meanings. Choose one map of terminology and be consistent.
  • Specify drag and drop interface for json
  • Specify import method for images:
    • Paste external
    • Drag-and-drop
    • Use file input
  • Ctrl + V is platform-dependent
  • Make it clear that there is no infinite paper mode (maybe add reference to the issue)
  • Add TOC?
  • Specify what "demo" means. E.g. my demo doesn't use a custom build.
  • Document all npm scripts more carefully.
  • In implementation details talk about files, versioning
  • Add a faq
    • How to recover "corrupted" V0 JSON documents
  • Document mobile mode
  • Document localStorage
  • Specify that it is client-side
  • Document #81 #34
  • Document layering order (esp. precedence when using move tool)
  • Require pull requests to update documentation, even if changes are only internal and not exposed
    • Locality of documentation is more important

Mobile gestures

  • Two-finger zoom and rotate objects when move tool is activated and an object is selected
  • Show context menu on two-finger click or long press? Not really necessary on mobile but it's still good to be able to change styles

Failed to compile.

Module parse failed: Cannot use keyword 'await' outside an async function (67:20)
src/lib/clipboard.ts 67:20
File was processed with these loaders:
 * ./node_modules/@pmmmwh/react-refresh-webpack-plugin/src/loader/index.js
 * ./node_modules/awesome-typescript-loader/dist/entry.js
You may need an additional loader to handle the result of these loaders.
|                 if (obj._objects) {
|                     obj.canvas = this.canvas;
>                     await obj.forEachObject((object) => {
|                         this.canvas.getNextId().then((id) => {
|                             object.id = id;

Issue is due to clipboard.ts

ui improvements

  • tooltips for the toolbar
  • something that pops up near your cursor when you right click (as in this)
  • add other keyboard layouts
  • add right-handed keybindings

add drawing features

  • change style of selected objs with keybinding (and add to history)
  • add style for pen width, in discrete steps
  • have an infinite paper mode
    • add panning with space
    • add zooming (with a / s? so unpaged?)
  • make eraser not use bounding box
  • make selection not use bounding box?

Decouple components

  • Convert almost everything to private variables
  • Hide details which enter the presentation layer into their own class?

I thought this was already an issue.

Pasted images should be size-capped

Pasting large or high-res images can completely cover the screen, even on large high-res monitors. Images should be capped by percentage of total screen space, by each dimension independently. Maybe cap at 80% height and 80% width.

Warning on changing URL/page

I've accidentally navigated away from the page, losing all my content, more times than I'd like to admit. This is completely human error, but could be sorted in software. When I click the back button on my mouse I got back to the new tab page, it's right where my thumb sits, so accidental taps are common. If I use my pen this isn't a problem but sometimes I switch to a GUI of something to show rather than whiteboard.

I've seen sites that are active have a pop up "are you sure" box. Simple yes or not to allow or stop.

Undo-redo for images isn't guaranteed

Paste an image (clipboard, or upload from input in latest commit) and do undo-redo. After some number of iterations (usually first), image will not appear. Continue to do it; eventually it will reappear.

Issue is at least as old as 816493c and occurs on CJ's demo too.
(@cjquines please put the commit hash as a comment in the hosted html file)

Feature Request - Paste external images in

Paste external images in from clipboard. I often talk about systems talking to other systems, for example. "git talking to github". This request is to be able to paste images, such as the GitHub logo, so that I can draw connectivity/activity/etc between components.

Support for image types that have transparency, such as PNG, would allow them to fit nicely into the board.
Ability to move and scale the images would allow them to fit into the rest of the content.

undoing / redoing transforms of multiple objects not exact

reproduce: make two objects, select both, scale both, undo, redo

see qboard.ts objectModified, which tries to save e.target.toJSON and partially revert it. undoing then redoing is not the same; indicates that maybe something is wrong with oldObject?

alternatively, maybe should try to use transform matrix, see https://stackoverflow.com/questions/38999034/how-does-transforming-points-with-a-transformmatrix-work-in-fabricjs/53710375#53710375

Export to pdf hangs

Reproduce: Import https://pihart.github.io/qboard/demos/123.json (included as text below), navigate to second page, export.

[{"version":"3.6.3","objects":[{"type":"path","version":"3.6.3","originX":"left","originY":"top","left":465.88,"top":164.87,"width":231.32,"height":402.2,"fill":null,"stroke":"#000000","strokeWidth":4,"strokeDashArray":[0,0],"strokeLineCap":"round","strokeDashOffset":0,"strokeLineJoin":"round","strokeMiterLimit":10,"scaleX":1,"scaleY":1,"angle":0,"flipX":false,"flipY":false,"opacity":1,"shadow":null,"visible":true,"clipTo":null,"backgroundColor":"","fillRule":"nonzero","paintFirst":"fill","globalCompositeOperation":"source-over","transformMatrix":null,"skewX":0,"skewY":0,"id":1,"strokeUniform":false,"path":[["M",467.87554714340115,313.20681599006025],["Q",467.87954714340117,313.20281599006023,468.35257106478196,312.25693751285155],["Q",468.8255949861627,311.3110590356428,472.3733285306363,308.00051142710925],["Q",475.9210620751099,304.6899638185756,495.078837651032,287.19126611360787],["Q",514.2366132269541,269.6925684086401,529.8466191689907,256.6867889601311],["Q",545.4566251110274,243.68100951162205,554.2077300589251,236.35050092636553],["Q",562.9588350068227,229.019992341109,580.6975027291907,215.06832539482554],["Q",598.4361704515586,201.11665844854204,614.9922603257687,190.0026269338848],["Q",631.5483501999788,178.8885954192276,643.6106225975418,173.44980770612582],["Q",655.6728949951048,168.01101999302404,659.6936524609591,167.30161564540032],["Q",663.7144099268136,166.59221129777663,670.5733830997763,168.48395923162843],["Q",677.432356272739,170.3757071654802,683.5817394295127,178.41566520118892],["Q",689.7311225862866,186.45562323689762,692.3328082879987,202.7719502939402],["Q",694.9344939897106,219.08827735098276,695.4075179110914,239.18811831686037],["Q",695.8805418324722,259.287959282738,695.170987905695,271.3478782951696],["Q",694.461433978918,283.4077973076013,692.3328082879985,309.41934718405366],["Q",690.2041825970791,335.4308970605061,688.3120508221441,360.0236292211453],["Q",686.4199190472092,384.61636138178454,685.9468951258284,406.844424411099],["Q",685.4738712044477,429.07248744041345,685.9468951258284,440.1865279756364],["Q",686.4199190472092,451.3005685108593,687.602496895367,470.69103219081023],["Q",688.7850747435249,490.08149587076116,690.4406765130636,505.2154613004443],["Q",692.0962782826023,520.3494267301274,693.5153861361564,531.2270201974624],["Q",694.9344939897106,542.1046136647973,695.6440479164876,546.1245385592574],["Q",696.3536018432646,550.1444634537177,697.2996496860262,555.8197162758388],["Q",698.2456975287878,561.4949690979599,698.7187214501686,564.3326045295862],["Q",699.1917453715494,567.1702399612125,699.1917453715494,568.1161003972898],["L",699.1917453715494,569.0659608333672]]},{"type":"path","version":"3.6.3","originX":"left","originY":"top","left":520.27,"top":526.92,"width":365.19,"height":26.9,"fill":null,"stroke":"#000000","strokeWidth":4,"strokeDashArray":[0,0],"strokeLineCap":"round","strokeDashOffset":0,"strokeLineJoin":"round","strokeMiterLimit":10,"scaleX":1,"scaleY":1,"angle":0,"flipX":false,"flipY":false,"opacity":1,"shadow":null,"visible":true,"clipTo":null,"backgroundColor":"","fillRule":"nonzero","paintFirst":"fill","globalCompositeOperation":"source-over","transformMatrix":null,"skewX":0,"skewY":0,"id":2,"strokeUniform":false,"path":[["M",522.2741281586627,555.8237343169703],["Q",522.2781281586628,555.8197343169703,523.697236012217,555.5832692079509],["Q",525.1163438657711,555.3468040989316,530.5561730957678,554.4009256217228],["Q",535.9960023257645,553.455047144514,546.8757329645816,550.8538948630385],["Q",557.7554636033987,548.252742581563,583.7721762628717,543.9963345369521],["Q",609.7888889223447,539.7399264923412,623.5067991788582,538.0846166058116],["Q",637.2247094353717,536.4293067192821,668.9177813302376,534.5375858471273],["Q",700.6108532251036,532.6458649749726,729.9388055130657,531.4635213887445],["Q",759.2667578010279,530.2811778025164,784.3373865283273,530.0446766112343],["Q",809.4080152556268,529.8081754199521,819.3416619622706,529.5717103109328],["Q",829.2753086689142,529.3352452019135,844.8853507003628,529.0987620517628],["Q",860.4953927318113,528.8622789016121,873.9767729829285,529.0987620517628],["L",887.4621532340458,529.3392452019135]]}],"background":"white"},{"version":"3.6.3","objects":[{"type":"path","version":"3.6.3","originX":"left","originY":"top","left":420.94,"top":245.15,"width":475.93,"height":339.07,"fill":null,"stroke":"#000000","strokeWidth":4,"strokeDashArray":[0,0],"strokeLineCap":"round","strokeDashOffset":0,"strokeLineJoin":"round","strokeMiterLimit":10,"scaleX":1,"scaleY":1,"angle":0,"flipX":false,"flipY":false,"opacity":1,"shadow":null,"visible":true,"clipTo":null,"backgroundColor":"","fillRule":"nonzero","paintFirst":"fill","globalCompositeOperation":"source-over","transformMatrix":null,"skewX":0,"skewY":0,"id":3,"strokeUniform":false,"path":[["M",422.9375889134024,290.03289252466845],["Q",422.9415889134024,290.02889252466844,424.1241667615603,289.319479156479],["Q",425.3067446097181,288.6100657882896,439.4976787876125,283.17128709575354],["Q",453.6886129655068,277.7325084032174,478.5227477768219,270.6384468858489],["Q",503.35688258813707,263.54438536848033,517.0747928446506,260.4703118895318],["Q",530.7927031011641,257.39623841058324,581.4070205665557,252.1939067859351],["Q",632.0213380319475,246.991575161287,645.5027182830648,247.22804929087204],["Q",658.9840985341822,247.46452342045708,668.9177813302376,247.70100657060777],["Q",678.8514641262932,247.9374897207585,688.5485808275405,250.53862396110264],["Q",698.2456975287878,253.1397582014468,700.8473832304999,257.3962023283205],["Q",703.449068932212,261.6526464551942,700.3743593091192,277.4960432941981],["Q",697.2996496860263,293.339440133202,673.4115627174729,330.4650305448773],["Q",649.5234757489193,367.5906209565526,637.4612033513561,383.19755268653716],["Q",625.398930953793,398.8044844165217,603.4029757601744,431.4371746128696],["Q",581.4070205665558,464.06986480921756,566.7430624672808,491.26380337472654],["Q",552.0791043680057,518.4577419402355,546.4027090432007,535.7199294333554],["Q",540.7263137183959,552.9821169264754,541.435867645173,561.7314883303735],["Q",542.1454215719501,570.4808597342716,544.7471072736622,574.0278904929559],["Q",547.3487929753743,577.5749212516401,561.3031971478722,582.3042955965525],["Q",575.2576013203702,587.0336699414648,604.3490236029361,584.6689827690086],["Q",633.4404458855018,582.3042955965525,670.5733830997763,574.7372677788825],["Q",707.7063203140508,567.1702399612125,725.9180119577995,563.1502609433581],["Q",744.1297036015482,559.1302819255038,776.0593055018104,552.2726855171545],["Q",807.9889074020726,545.4150891088053,833.2961022241805,540.685714763893],["Q",858.6032970462882,535.9563404189806,872.0846772974054,535.0104799829032],["Q",885.5660575485226,534.0646195468258,888.8772610875999,534.5375858471273],["Q",892.1884646266772,535.0105521474287,895.7361981711508,536.4293247604135],["Q",899.2839317156245,537.8480973733981,898.3378838728629,540.2127845458542],["L",897.3878360301012,542.5814717183105]]}],"background":"white"},{"version":"3.6.3","objects":[{"type":"path","version":"3.6.3","originX":"left","originY":"top","left":542.51,"top":175.88,"width":385,"height":702.38,"fill":null,"stroke":"#000000","strokeWidth":4,"strokeDashArray":[0,0],"strokeLineCap":"round","strokeDashOffset":0,"strokeLineJoin":"round","strokeMiterLimit":10,"scaleX":1,"scaleY":1,"angle":0,"flipX":false,"flipY":false,"opacity":1,"shadow":null,"visible":true,"clipTo":null,"backgroundColor":"","fillRule":"nonzero","paintFirst":"fill","globalCompositeOperation":"source-over","transformMatrix":null,"skewX":0,"skewY":0,"id":4,"strokeUniform":false,"path":[["M",614.9882603257686,210.10649496145948],["Q",614.9922603257686,210.10249496145948,616.411332089911,208.9201513752314],["Q",617.8304038540532,207.7378077890033,648.8139579115539,195.67788877657165],["Q",679.7975119690547,183.61796976414,693.5154222255683,181.48976574183453],["Q",707.2333324820819,179.36156171952905,732.7769851307622,178.4156742217546],["Q",758.3206377794426,177.46978672398018,781.9721947425998,181.01681748266446],["Q",805.623751705757,184.56384824134872,825.964105129837,190.71203128150853],["Q",846.3044585539169,196.86021432166834,854.3459734856256,200.17077997133327],["Q",862.3874884173342,203.4813456209982,871.1385933652319,210.10246789976242],["Q",879.8896983131297,216.7235901785266,883.2009018522069,223.81765169589517],["Q",886.5121053912842,230.91171321326374,884.3834797003648,243.4445534231684],["Q",882.2548540094454,255.97739363307306,877.2880126114176,266.6184859091259],["Q",872.3211712133899,277.2595781851788,849.3791681770097,303.0346719731775],["Q",826.4371651406295,328.8097657611762,791.9058775386553,358.60482052589794],["Q",757.3745899366811,388.3998752906196,733.4865390575394,412.51967723322014],["Q",709.5984881783976,436.6394791758207,703.449068932212,444.20648895235934],["Q",697.2996496860263,451.77349872889795,691.3867604452371,461.7051776367614],["Q",685.4738712044477,471.6368565446248,686.6564490526056,475.18388730330906],["Q",687.8390269007634,478.73091806199335,699.9013353877384,482.0415197939211],["Q",711.9636438747134,485.3521215258488,724.7354701990535,486.06149881177544],["Q",737.5072965233936,486.77087609770206,772.5116080467487,487.48027142476013],["Q",807.5159195701038,488.1896667518182,837.7899197008275,491.7366975105025],["Q",868.0639198315511,495.2837282691867,889.8233450197733,503.32370434602683],["Q",911.5827702079956,511.36368042286693,916.7861055220078,515.3836053173271],["Q",921.98944083602,519.4035302117873,926.4832222232551,531.2269660740683],["Q",930.9770036104902,543.0504019363492,922.9354886787816,564.805534747625],["Q",914.8939737470729,586.5606675589006,890.0598389357579,616.119257214603],["Q",865.2257041244427,645.6778468703053,847.723566407471,661.9941739273479],["Q",830.2214286904995,678.3105009843906,783.8643626069465,712.5984649850053],["Q",737.5072965233936,746.88642898562,680.9800898172125,785.6673202632592],["Q",624.4528831110315,824.4482115408982,584.4817301896487,852.3515273923338],["L",544.5065772682658,880.2588432437694]]}],"background":"white"}]

Import pdf

For each page x in pdf, add the content of x as a new page.

Use images if easier, but later change it to get the actual vectors from the pdf.

Add drag and drop for JSON

Should not overwrite existing document.

Either it should

  • prompt "are you sure" before replacing document, or
  • append pages like before (preferred)

Context menu should change styles of selected object

Currently they only change the global style for future drawings. Also, when an object is selected, the context menu shouldn't even touch the global styles (at least when the context menu was triggered by clicking on the selected object)

Set a file output format

I like the exported PDF to be qboard date time.pdf or something that won't give me file(n).pdf.

It lost one of my pages

Page numbers k and k+1 both got rendered as what should've been page k + 1's content. When exported as JSON, obj.pages[k - 1] and obj.pages[k] are identical, so the content was lost. Same when exporting as PDF, so I think internally pagesJSON was incorrectly modified due to a race condition. (Page number k was a very large page in terms of bezier curves so maybe that's why.)

Not sure how to reproduce.

Desktop version

Desktop verison where I can keep old qboards and keep my keybindings. A systems similar to Onenote would be nice.

Text + TeX

Add text boxes (w/ bold, italics, subscript, superscript, highlighting, etc. -- most I probably won't use, but it's a good thing to add regardless) and latex rendering.

Edit: this is very obviously an enhancement, not something super important (except to me, latex is life).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.