builderscon tokyo 2018『Electronによるアプリケーション開発事情2018』
ElectronʹΑΔΞϓϦέʔγϣϯ։ൃࣄ2018builderscon tokyo 2018@h3_poteto
View Slide
ࣗݾհ• Akira Fukushimaʢౡ ໌ʣ• github: h3poteto• twitter: h3_poteto• Mastodon: @[email protected]• ࣄɿterraform৬ਓ@scouty
એ
σεΫτοϓ͚ͷMastodonΫϥΠΞϯτΛ࡞͍ͬͯ·͢
ࠓ͜ͷΞϓϦέʔγϣϯΛࡐʹElectronͷΛ͠·͢
એऴΘΓ
ࠓͷ• ElectronͰΞϓϦέʔγϣϯ࡞ΔͷϚδͰָͩΑʢͲΜͲΜָʹͳΓͭͭ͋Δ• ͰSNSͷΫϥΠΞϯτ࡞Δͷେม• ւ֎͔Βͷҙ֎ͳԠ͋ͬͨ• ΈΜͳMastodonͬͯ΄͍͠
ElectronͰΞϓϦέʔγϣϯΛ։ൃ͢Δ
Electron?• ੲAtom-shellͱݺΕ͍ͯͨ• Chromium + Node.js• Windows/Mac/Linux͚ͷΞϓϦέʔγϣϯ͕࡞ΕΔ
ͭ·Γ• දࣔ෦ϒϥβͳͷͰWebϑϩϯτΤϯυͷٕज़Λ͑Δ• React.js/Vue.jsࡌͤΒΕΔ• SPAͰΞϓϦ͕࡞ΕΔ
vue-cliͰܗ͕࡞ΕΔ$ npm install -g vue-cli$ vue init simulatedgreg/electron-vue \whalebird
vue-cliͰͷܗ• webpackʹΑΔ։ൃ࣌ͷϏϧυઃఆ• auto-reload• ςετͷܗ
Electronͷجຊߏ• mainϓϩηε: όοΫάϥϯυδϣϒɼΞϓϦέʔγϣϯͷཧΛߦ͏• rendererϓϩηε: jsΛ࣮ߦ͠html, cssΛϨϯμϦϯά͢Δ
rendererϓϩηεଆΛͯ͢SPAʹ͢Δ͜ͱ͕Մೳ͜͜ͰReact.js/Vue.js͕͑Δ
خ͍͜͠ͱᶃReact.js/Vue.js(Flux)ΛGUIΞϓϦέʔγϣϯͰ͑Δ
iOS։ൃ͍ͯͨ͜͠Ζ• ViewController͕ແݶʹଠΔʂ• delegate͕ͦ͜Βதʹ……• ϞσϧͲ͏͜͏ͱ͍͏ΑΓঢ়ଶը໘ભҠͷϩδοΫ͕େม
class SwipeViewController: UIViewController,SwipeViewDelegate, SwipeViewDataSource,UINavigationControllerDelegate, UITabBarControllerDelegate {func navigationController(_ navigationController:UINavigationController, didShow viewController:UIViewController, animated: Bool) {if (type(of: viewController) ===SwipeViewController.self) {for i in 0 ..< self.streamList.count() {self.viewItems[i].fCellSelect = false}}}}͛͢ʔ͍ͬͺ͍Delegateͯ͠Δ
React.js/Vue.sj(Flux)ʹ͢Δͱ• ࠩϨϯμϦϯάReact.js/Vue.jsͷ͕ͬͯ͘ΕΔ͜ͱ͕લఏ• delegateͱ͔ඞཁͳ͍• Flux͕σʔλͷྲྀΕΛҰํʹͯ͘͠ΕΔ• GUIΞϓϦέʔγϣϯͳͷʹݟ௨͕͠ྑ͍
:message="message":filter="filter":focused="message.uri === focusedId":overlaid="modalOpened"@update=“updateToot"@delete=“deleteToot"@focusNext="focusNext"@focusPrev="focusPrev"@selectToot="focusToot(message)">focusToot (message) {this.focusedId = message.uri}
خ͍͜͠ͱᶄίϯτϦϏϡʔλ͕૿͑Δ
WhalebirdͷίϯτϦϏϡʔλ• ΄΅jsͷٕज़ͳͷͰjsք۾ͷਓ͕ίϯτϦϏϡʔτ͍͢͠ʢ͜͜ͷϘϦϡʔϜ͕ଟ͍
خ͍͜͠ͱᶅΫϩεϓϥοτϑΥʔϜ
ΫϩεϓϥοτϑΥʔϜ• Windows/Mac/LinuxͰಉ͡ιʔεͷ··ϏϧυՄೳ• ͨͩ͠Ұ෦Mac͚ͷػೳ࣮͞Ε͍ͯΔ
ྫ: Dockϝχϡʔϝχϡʔ༰͕ΧελϚΠζՄೳelecron-context-menu
خ͍͜͠ͱᶆΞΫςΟϒʹ։ൃ͞Ε͍ͯΔ
ElectronͷϦϦʔεׂͱ׆ൃ• v2.0.8 - 2018/08/23• v2.0.7 - 2018/08/09• v2.0.6 - 2018/08/013.0.0४උத: v3.0.0-beta.8
ΞϓϦέʔγϣϯΛύοέʔδϯάˍϦϦʔε
Let’s ElectronΈ͍ͨͳهࣄ͍ͬͺ͍͋Δ͚ͲϦϦʔεʹؔ͢Δهࣄ͕΄ͱΜͲͳ͍
֮͑ͯ΄͍͜͠ͱ:electron-builder͕͋Ε͍͍ͩͨղܾ͢Δ
• electron-packager• electron-builderͱ͍͏ͷ͕͋Δ
electron-packager• webpackͰίϯύΠϧ͞ΕͨϑΝΠϧ܈ΛΞϓϦέʔγϣϯͱͯ͠·ͱΊΔ• جຊతʹ͜Ε͔ͬͯ͘͠Εͳ͍• ίϚϯυϥΠϯ
electron-builder• ΞϓϦέʔγϣϯͷύοέʔδϯά• ূ໌ॻͷՃ• ֤छΠϯετʔϧՄೳͳϑΝΠϧܗࣜʹѹॖʢ.dmg, .deb, .rpm, .exeʣ• package.jsonʹઃఆ͕ॻ͚Δ• ެࣜυΩϡϝϯτ͕๛: https://www.electron.build/
"build": {"productName": "Whalebird","appId": "org.whalebird.desktop","directories": {"output": "build"},"mac": {"icon": "build/icons/icon.icns","target": ["dmg"],"category": "public.app-category.social-networking"},
͓͔͛ͰϦϦʔεܗ͕ࣜ๛• AppStore(.pkg)• .dmg• .exe• .deb• .rpm• .tar.bz2• snapcraft (.snap)
ͪΐͬͱಛघͳઃఆྫ• ΞΠίϯ• ֎෦ϦιʔεʢԻʣ• ূ໌ॻ• MASʢMac App Storeʣ
ΞΠίϯ• Mac/Windows: Ϗϧυ࣌ʹຒΊࠐΉ• Linux: Ұ෦main.jsͰ֎෦ϑΝΠϧΛࢦఆ• ը૾ϑΝΠϧasarѹॖ͞Ε͍ͯͯ෦ͷͷΛࢦఆՄೳ
"build": {"productName": “Whalebird","files": ["dist/electron/**/*","build/icons/*"],"mac": {"icon": "build/icons/icon.icns","target": ["dmg"],"category": "public.app-category.social-networking"},"win": {"icon": "build/icons/icon.ico","target": "nsis"},iconͷࢦఆ
mainWindow = new BrowserWindow({titleBarStyle: 'hidden',useContentSize: true,icon: path.resolve(__dirname, '../../build/icons/256x256.png')}BrowserWindowͷىಈΦϓγϣϯͰΞΠίϯΛࢦఆ
֎෦ϦιʔεͷಡΈࠐΈ• ԻϑΝΠϧΛಡΈࠐΈ͍ͨ߹͕͋Δ• asarѹॖͷϑΝΠϧಡΈऔΕͳ͍• ϏϧυઃఆͰasarѹॖ͔Βআ֎͢Δඞཁ͕͋Δ
"build": {"productName": "Whalebird","appId": "org.whalebird.desktop","directories": {"output": "build"},"extraResources": ["build/sounds/*"],"files": ["dist/electron/**/*","build/icons/*"],ԻΛextraResourcesʹࢦఆ
const soundBasePath = process.env.NODE_ENV === 'development'? path.join(__dirname, '../../build/sounds/'): path.join(process.resourcesPath, 'build/sounds/')const sound = path.join(soundBasePath, 'operation_sound01.wav')simplayer(sound, (err) => {if (err) log.error(err)})͜͜asar֎ͷϑΝΠϧΛࢦఆ͢Δඞཁ͕͋Δ
Mac༻ͷূ໌ॻ• Developer ID Installer• Developer ID Applicationelectron-builderͳΒϏϧυ࣌ʹKeyChainAccessͷূ໌ॻΛࣗಈͰͯͯ͘ΕΔ
MAS͚ͩಛผѻ͍• electron-builderͰCodeSign·ͰͰ͖ͳ͔ͬͨ• electron-packagerͰϏϧυޙɼࣗͰCodeSign• plistΛࣗͰॻ͘ඞཁ͕͋Δ• ͦΕΛApplication LoaderͰΞοϓϩʔυ͢Δ• ͋ͱiTunes ConnectͰόʔδϣϯΞοϓ
#!/bin/zsh -f# Name of your app.APP="Whalebird"# The path of your app to sign.APP_PATH="./packages/Whalebird-mas-x64/Whalebird.app"# The path to the location you want to put the signed package.RESULT_PATH="./packages/$APP.pkg"# The name of certificates you requested.APP_KEY="3rd Party Mac Developer Application: Akira Fukushima (HB4N6B2YVM)"INSTALLER_KEY="3rd Party Mac Developer Installer: Akira Fukushima (HB4N6B2YVM)"# The path of your plist files.CHILD_PLIST="./plist/child.plist"PARENT_PLIST="./plist/parent.plist"LOGINHELPER_PLIST="./plist/loginhelper.plist"FRAMEWORKS_PATH="$APP_PATH/Contents/Frameworks"# At first, rename app.asar.unpacked directory.# Because electron-builder does not store app.asar.unpacked directory.# I want to store unpacked files at the same directory as electron-builder.mv $APP_PATH/Contents/Resources/app.asar.unpacked/* $APP_PATH/Contents/Resources/codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/Electron Framework.framework/Versions/A/Electron Framework"codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/Electron Framework.framework/Versions/A/Libraries/libffmpeg.dylib"codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/Electron Framework.framework/Versions/A/Libraries/libnode.dylib"codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/Electron Framework.framework"codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/$APP Helper.app/Contents/MacOS/$APP Helper"codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/$APP Helper.app/"codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/$APP Helper EH.app/Contents/MacOS/$APP HelperEH"codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/$APP Helper EH.app/"codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/$APP Helper NP.app/Contents/MacOS/$APP HelperNP"codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/$APP Helper NP.app/"codesign -s "$APP_KEY" -f --entitlements "$LOGINHELPER_PLIST" "$APP_PATH/Contents/Library/LoginItems/$APP LoginHelper.app/Contents/MacOS/$APP Login Helper"codesign -s "$APP_KEY" -f --entitlements "$LOGINHELPER_PLIST" "$APP_PATH/Contents/Library/LoginItems/$APP LoginHelper.app/"codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$APP_PATH/Contents/MacOS/$APP"codesign -s "$APP_KEY" -f --entitlements "$PARENT_PLIST" "$APP_PATH"productbuild --component "$APP_PATH" /Applications --sign "$INSTALLER_KEY" "$RESULT_PATH"
#!/bin/zsh -f# Name of your app.APP="Whalebird"# The path of your app to sign.APP_PATH="./packages/Whalebird-mas-x64/Whalebird.app"# The path to the location you want to put the signed package.RESULT_PATH="./packages/$APP.pkg"# The name of certificates you requested.APP_KEY="3rd Party Mac Developer Application: Akira Fukushima (HB4N6B2YVM)"INSTALLER_KEY="3rd Party Mac Developer Installer: Akira Fukushima (HB4N6B2YVM)"# The path of your plist files.CHILD_PLIST="./plist/child.plist"PARENT_PLIST="./plist/parent.plist"LOGINHELPER_PLIST="./plist/loginhelper.plist"FRAMEWORKS_PATH="$APP_PATH/Contents/Frameworks"# At first, rename app.asar.unpacked directory.# Because electron-builder does not store app.asar.unpacked directory.# I want to store unpacked files at the same directory as electron-builder.mv $APP_PATH/Contents/Resources/app.asar.unpacked/* $APP_PATH/Contents/Resources/codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/Electron Framework.framework/Versions/A/Electron Framework"codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/Electron Framework.framework/Versions/A/Libraries/libffmpeg.dylib"codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/Electron Framework.framework/Versions/A/Libraries/libnode.dylib"codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/Electron Framework.framework"codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/$APP Helper.app/Contents/MacOS/$APP Helper"codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/$APP Helper.app/"codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/$APP Helper EH.app/Contents/MacOS/$APP HelperEH"codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/$APP Helper EH.app/"codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/$APP Helper NP.app/Contents/MacOS/$APP HelperNP"codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/$APP Helper NP.app/"codesign -s "$APP_KEY" -f --entitlements "$LOGINHELPER_PLIST" "$APP_PATH/Contents/Library/LoginItems/$APP LoginHelper.app/Contents/MacOS/$APP Login Helper"codesign -s "$APP_KEY" -f --entitlements "$LOGINHELPER_PLIST" "$APP_PATH/Contents/Library/LoginItems/$APP LoginHelper.app/"codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$APP_PATH/Contents/MacOS/$APP"codesign -s "$APP_KEY" -f --entitlements "$PARENT_PLIST" "$APP_PATH"productbuild --component "$APP_PATH" /Applications --sign "$INSTALLER_KEY" "$RESULT_PATH"codesignίϚϯυΛ͑ྑ͍
com.apple.security.app-sandboxcom.apple.security.application-groupsHB4N6B2YVM.org.whalebird.desktopcom.apple.security.files.user-selected.read-onlycom.apple.security.network.client
com.apple.security.app-sandboxcom.apple.security.application-groupsHB4N6B2YVM.org.whalebird.desktopcom.apple.security.files.user-selected.read-onlycom.apple.security.network.client͜͜Ͱ• ωοτϫʔΫΞΫηε• ϑΝΠϧΞΫηεΛڐՄ͢Δ
͜ͷ͋ͱ৹͕ࠪ͋Δʂ
MAS݁ߏͭΒ͍
͜͜·Ͱͷ·ͱΊ• electron-builderϚδΜΓ• electron-builderͷਐา͕͍ͷͰ͜Εͬͱ͚ؒҧ͍ͳ͍• MAS͍ͭେม
MastodonͷΫϥΠΞϯτΛ࡞Δ
ͳͥMastodonͷΫϥΠΞϯτΛ࡞Δͷ͔
σεΫτοϓ͚ͷΫϥΠΞϯτ͕ͳ͍ɼຊʹগͳ͍• MstdnʢࣗͰjsonϑΝΠϧΛ༻ҙͯ͠tokenΛೖΕΔʣ• The Desk• TsuruʢόΠφϦͷͳ͍ʣ
ͳ͍ͷͰ͋ΕࣗͰͭ͘Ζ͏
Whalebirdͷίϯηϓτ• LinuxͰ͑ΔͷΛ• Slackʹ׳Ε͍ͯΔͷͰSlackΆ͍ݟͨ• γϣʔτΧοτͱʹ͔͘ଟ͘࠷ڧͷTwitterΫϥΠΞϯτઓ૪Λࢥ͍ग़͢
ॳ൛͕Ͱ͖ͨ
ւ֎͔ΒͷԠ
ʢӳޠαϙʔτ͔ͨ͠Β͔ʣ࠷ॳւ֎͔ΒԠ͕
ϦϦʔεͯ͠࠷ॳͷҰिؒ
ྑ͍ʂ͚ͩͲElectron͔……Έ͍ͨͳԠ͔Γ
ͦΜͳʹElectronͬͯධѱ͍ͷʁຊͰ͋·Γฉ͔ͳ͔͚ͬͨͬͲ
ධͷѱ͞• ϝϞϦফඅ͕ଟ͍• SlackΛىಈ͢Δ͚ͩͰ500MBҎ্ϝϞϦΛ͍͔࣋ͬͯΕΔ• ࠷దԽ͞Εͯͳ͍ͷͰϝϞϦফඅ͕ଟ͍• Javaͷํ͕͍ܰ• node.js͕ݏ͍
ϝϞϦͱઓ͏
࠷ظ1GBҎ্͍͔࣋ͬͯΕͨ
Ͳ͜ͰϝϞϦΛফඅ͍ͯ͠Δͷ͔ʁ
ࢼͯ͠ΈΔ• StreamingΛࢭΊͨঢ়ଶͰ͍Ζ͍Ζ৮ͬͯΈΔ• StreamingΛࢭΊͨঢ়ଶͰ์ஔϝϞϦϦʔΫ͔ʁ
StreamingࢭΊ͍ͯΔͱ૿͑ͳ͍ʂผʹϝϞϦϦʔΫ͍ͯ͠ΔΘ͚Ͱͳ͍ʂ
StreamingʹΑΔϝϞϦফඅ• ຊΛ૿ͯ͠ΈΔʁ
StreamingʹΑΔϝϞϦফඅ• όοΫάϥϯυͰStreaming͢Δ͚ͩͰରͯ͠ϝϞϦΛফඅ͠ͳ͍ʂ
͏গ͠ࢼ͢• ྲྀͷ͍ΠϯελϯεͰ์ஔʢmikutterʣ• ྲྀͷ͍ΠϯελϯεͰ์ஔʢjpʣ
໌Β͔ʹྲྀ͕͍΄͏͕ϝϞϦফඅ͕ଟ͍
͜Ε͠ϨϯμϦϯάͳͷͰʁ
WhalebirdͷλΠϜϥΠϯඳը• Streaming͞ΕͨͷΛͯ͢htmlͱͯ͠ද͍ࣔͯͨ͠• ͭ·Γϒϥβͷ࣮ʹؙ͛• FireFoxͰڊେϖʔδΛ։͍ͨΒॏ͍ ʢ͔ͩΒΈΜͳϖʔδωʔγϣϯ͢ΔΜͩ
ଞͲ͏͍ͯ͠Δͷ͔ʁ
iOSͷ߹• UITableViewදࣔ͞Ε͍ͯΔ෦͔͠ϨϯμϦϯά͍ͯ͠ͳ͍• ӅΕ͍ͯΔ·ͰؚΊͨεΫϩʔϧྔܭࢉ͍ͯ͠Δ• εΫϩʔϧ͞Εͨࡍදࣔ͢Δલʹ༰ΛϨϯμϦϯά
ਤ
දࣔ͞Ε͍ͯͳ͍෦ϨϯμϦϯά͍ͯ͠ͳ͍
UITableViewController• cellForRowAt: ηϧͷதΛϨϯμϦϯά• heightForRowAt: ηϧͷߴ͞Λࢉग़• estimatedHeightForRowAt: ະදࣔΛؚΊͯηϧͷߴ͞Λࢉग़
ྲྀੴʹ͜ΕύΫΕͳ͍
ϙΠϯτɿඳը͢Δൣғݟ͍͑ͯΔ෦͘Β͍Ͱे
ElectronͰͲ͏͢Δ͔ʁ• λΠϜϥΠϯΛͯ͢දࣔ͢ΔͷΛΊΔ• ࠷৽40݅ͷΈΛදࣔ͠ɼඞཁͰ͋ΕLazyLoading• StreamingͰߋ৽͞Εͨ߹ɼݹ͍ͷΛফͯ͠40݅ʹอͭ
εΫϩʔϧΠϕϯτΛͱʹ੍ޚͯ͠Δ
200MBΛΔʂ
ѹత͡Όͳ͍͔ʂ
ϙΠϯτɿVue.jsͷύϑΥʔϚϯεʹؾΛΔ
vue.jsͷύϑΥʔϚϯε• v-ifͱv-show• v-if: ସ࣌ʹhtml͕ੜ͞ΕϨϯμϦϯά͞ΕΔ• v-show: ͡Ί͔ΒϨϯμϦϯά͞Ε͍ͯΔ͕ɼdisplay: none͞Ε͍ͯΔ͚ͩ
v-ifͱv-show• v-ifͷସ࣌ϨϯμϦϯάίετഅࣛʹͳΒͳ͍• ͔͠͠ɼඞཁͷͳ͍ͱ͜ΖΛv-showʹ͢ΔͱͣͬͱϝϞϦΛফඅ͠ଓ͚Δ
͜͜ਖ਼ղ͕ͳ͍
࠷ۙͷWhalebird• ϝϞϦফඅ: 200MB ~ 500MB• 500MB͘Β͍·Ͱ͘ΔͱGC͞ΕͯϝϞϦফඅ͕ҰؾʹݮΔ• ը૾͕গͳ͍࣌ؒଳ͍ܰʂ ʢpawooͷਓ͝ΊΜͳ͍͞
࠷ۙͷWhalebird• ϕʔεʹͳ͍ͬͯΔElectronΛόʔδϣϯΞοϓ͢ΔͱϝϞϦফඅ͕ݮΔ• ύϑΥʔϚϯεChromiumʹ߹ΘͤͯͲΜͲΜྑ͘ͳΔ
͜ͷઌͷ࡞ઓ• ը૾ͷඇදࣔΦϓγϣϯ• τΡʔτ͕࿈ଓ͢Δ߹·ͱΊͯϨϯμϦϯάͰ͖ͳ͍͔ʁ
͓ӄ༷Ͱ࠷ۙͷԠྑ͍
APIΫϥΠΞϯτϥΠϒϥϦΛࣗ࡞͢Δ
ॳmastodon-apiͱ͍͏Node.jsͷϥΠϒϥϦΛར༻
͕ɼΤϥʔʹͳΔͱ͍͏ใࠂ͕ͪΒ΄Β
mastodon-api• POSTύϥϝʔλΛbodyͰͳ͘urlύϥϝʔλͱͯ͠ૹ৴͍ͯ͠Δ• Ұ෦αʔόͰͦΕΒ͕ڋ൱͞Ε͍ͯΔଞͷબࢶ͕ͳ͍
ͳ͍ͷͳΒࣗ࡞͠Α͏
megalodon• TypeScriptͰॻ͍ͨmastodonAPIΫϥΠΞϯτϥΠϒϥϦ• Streaming࣮ࡁΈ• OAuthΞϓϦέʔγϣϯొ༻ϝιου༻ҙ
public get(path: string, params = {}): Promise> {return axios.get(this.baseUrl + path, {headers: {'Authorization': `Bearer ${this.accessToken}`},params}).then((resp: AxiosResponse) => {const res: Response = {data: resp.data,status: resp.status,statusText: resp.statusText,headers: resp.headers}return res})}
όάͬͯͨ߹શ෦ࣗͰ࣏ͤΔ
ΠϯελϯεΛݐͯΔ͜ͱ͋Δ
ΠϯελϯεݪҼͷ͍߹Θͤଟ͍• ϩάΠϯ͕Ͱ͖ͳ͍• τΡʔτͰ͖ͳ͍• Streaming͕ಈ͔ͳ͍• ʑ……
࠷ۙ͋ͬͨ൵͍͠ࣄྫ• (mastodon͕͍ͬͯΔ)doorkeeper 4.3.0Ҏ্ Ͱnative_redirect_uriʹؔ͢Δόά͕ࠞೖ• mastodon: doorkeeper ~> 4.4.1• σεΫτοϓΞϓϦέʔγϣϯͰೝূ͕Ͱ͖ͳ͘ͳΔ
͔֬ΊΔ&ϓϧϦΫΛग़͢• खݩͰmastodonαʔόΛݐͯΔ: https://github.com/tootsuite/documentation/blob/master/Running-Mastodon/Development-guide.md• ࠶ݱͨ͠• doorkeeperʹissueཱͯͨΓɼmastodonʹϓϧϦΫΛૹͬͨΓ
ΫϥΠΞϯτ͚ͩͷͰͳ͍͜ͱ͕ଟ͍ͷͰɼαΫοͱΠϯελϯεΛཱͯΒΕΔΑ͏ʹ͓ͯ͘͠ͷॏཁ
·ͱΊ
ޭͨ͠ͳʔͱࢥ͏͜ͱ• ElectronͰ࡞ͬͨ͜ͱ• Vue.jsͱ͍͏બ• ӳޠݍͷྀ
ࣦഊͨ͠ͳʔͱࢥ͏͜ͱ• ͬͱૣ͘࡞ΕΑ͔ͬͨ• ͬͱૣ͘TypeScriptΛߟྀ͖ͩͬͨ͢• megalodon(APIΫϥΠΞϯτ)ϝϯς͍͢͠• దͳΦϒδΣΫτΛ͢͜ͱ͕ଟ͍
updateTimeFormat ({ dispatch, commit, state }, value) {const newGeneral = Object.assign({}, state.general, {timeFormat: value})const config = {general: newGeneral}ipcRenderer.send('update-preferences', config)ipcRenderer.once('error-update-preferences', (event, err) => {ipcRenderer.removeAllListeners('response-update-preferences')})ipcRenderer.once('response-update-preferences', (event, conf) => {ipcRenderer.removeAllListeners('error-update-preferences')dispatch('App/loadPreferences', null, { root: true })commit('updateGeneral', conf.general)})},actionͻͱ͔ͭ͠ҾΛऔΕͳ͍mainͱͷ௨৴ipcͰߦ͏ະͷΦϒδΣΫτ
શମతʹݟͯ• ElectronʢϦϦʔεํ๏ؚΊͯʣਐԽ͍ͯ͠ΔͷͰ͓͢͢Ί͍ͨ͠• ϝϞϦফඅରࡦՄೳ• Vue.jsͰGUIΞϓϦέʔγϣϯ։ൃ͢Δͷྑ͍
Mastodon͕շదʹͳͬͨͷͰTwitterΛݟΔ͜ͱ͕ݮͬͨ
͞Α͏ͳΒTwitterΫϥΠΞϯτ