├── media ├── icon_128.png ├── icon_256.png ├── screenshot.png ├── inbox_quiet.png ├── inbox_logged_in.png ├── tryitnowbutton.png ├── inbox_quiet_retina.png ├── inbox_not_logged_in.png ├── inbox_logged_in_retina.png └── inbox_not_logged_in_retina.png ├── .gitignore ├── background.html ├── _locales ├── en │ └── messages.json ├── en_GB │ └── messages.json ├── nb │ └── messages.json ├── et │ └── messages.json ├── sv │ └── messages.json ├── id │ └── messages.json ├── it │ └── messages.json ├── nl │ └── messages.json ├── da │ └── messages.json ├── sl │ └── messages.json ├── fil │ └── messages.json ├── de │ └── messages.json ├── fi │ └── messages.json ├── hr │ └── messages.json ├── ca │ └── messages.json ├── es_419 │ └── messages.json ├── pt_BR │ └── messages.json ├── hu │ └── messages.json ├── pt_PT │ └── messages.json ├── lv │ └── messages.json ├── es │ └── messages.json ├── ro │ └── messages.json ├── cs │ └── messages.json ├── pl │ └── messages.json ├── tr │ └── messages.json ├── fr │ └── messages.json ├── zh_CN │ └── messages.json ├── zh_TW │ └── messages.json ├── sk │ └── messages.json ├── lt │ └── messages.json ├── ko │ └── messages.json ├── ja │ └── messages.json ├── vi │ └── messages.json ├── he │ └── messages.json ├── ar │ └── messages.json ├── sr │ └── messages.json ├── th │ └── messages.json ├── ru │ └── messages.json ├── hi │ └── messages.json ├── bg │ └── messages.json ├── el │ └── messages.json └── uk │ └── messages.json ├── .jshintrc ├── AUTHORS.md ├── manifest.json ├── LICENSE ├── options.css ├── README.md ├── CHANGES.md ├── options.html ├── options.js └── background.js /media/icon_128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joeyespo/inbox-by-gmail-checker/HEAD/media/icon_128.png -------------------------------------------------------------------------------- /media/icon_256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joeyespo/inbox-by-gmail-checker/HEAD/media/icon_256.png -------------------------------------------------------------------------------- /media/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joeyespo/inbox-by-gmail-checker/HEAD/media/screenshot.png -------------------------------------------------------------------------------- /media/inbox_quiet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joeyespo/inbox-by-gmail-checker/HEAD/media/inbox_quiet.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Environment files 2 | build/ 3 | 4 | # OS-specific files 5 | .DS_Store 6 | Desktop.ini 7 | Thumbs.db 8 | -------------------------------------------------------------------------------- /media/inbox_logged_in.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joeyespo/inbox-by-gmail-checker/HEAD/media/inbox_logged_in.png -------------------------------------------------------------------------------- /media/tryitnowbutton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joeyespo/inbox-by-gmail-checker/HEAD/media/tryitnowbutton.png -------------------------------------------------------------------------------- /media/inbox_quiet_retina.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joeyespo/inbox-by-gmail-checker/HEAD/media/inbox_quiet_retina.png -------------------------------------------------------------------------------- /media/inbox_not_logged_in.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joeyespo/inbox-by-gmail-checker/HEAD/media/inbox_not_logged_in.png -------------------------------------------------------------------------------- /media/inbox_logged_in_retina.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joeyespo/inbox-by-gmail-checker/HEAD/media/inbox_logged_in_retina.png -------------------------------------------------------------------------------- /media/inbox_not_logged_in_retina.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joeyespo/inbox-by-gmail-checker/HEAD/media/inbox_not_logged_in_retina.png -------------------------------------------------------------------------------- /background.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /_locales/en/messages.json: -------------------------------------------------------------------------------- 1 | {"gmailcheck_name":{"message":"Google Mail Checker"},"gmailcheck_description":{"message":"Displays the number of unread messages in your Google Mail inbox. You can also click the button to open your inbox."},"gmailcheck_node_error":{"message":"Error: feed retrieved, but no <fullcount> node found"},"gmailcheck_exception":{"message":"exception: $1","placeholders":{"1":{"content":"$1"}}}} 2 | -------------------------------------------------------------------------------- /_locales/en_GB/messages.json: -------------------------------------------------------------------------------- 1 | {"gmailcheck_name":{"message":"Google Mail Checker"},"gmailcheck_description":{"message":"Displays the number of unread messages in your Google Mail inbox. You can also click the button to open your inbox."},"gmailcheck_node_error":{"message":"Error: Feed retrieved, but no <fullcount> node found"},"gmailcheck_exception":{"message":"exception: $1","placeholders":{"1":{"content":"$1"}}}} 2 | -------------------------------------------------------------------------------- /_locales/nb/messages.json: -------------------------------------------------------------------------------- 1 | {"gmailcheck_name":{"message":"Google e-post-sjekker"},"gmailcheck_description":{"message":"Viser antallet uleste meldinger i innboksen for Google Mail. Du kan ogs\u00e5 klikke p\u00e5 knappen for \u00e5 \u00e5pne innboksen."},"gmailcheck_node_error":{"message":"Feil: innmating hentet, men finner ingen <fullcount>-node"},"gmailcheck_exception":{"message":"unntak: $1","placeholders":{"1":{"content":"$1"}}}} 2 | -------------------------------------------------------------------------------- /_locales/et/messages.json: -------------------------------------------------------------------------------- 1 | {"gmailcheck_name":{"message":"Google'i meilikontrollija"},"gmailcheck_description":{"message":"Kuvab Google Maili postkastis olevate lugemata s\u00f5numite arvu. V\u00f5ite kl\u00f5psata ka nupul ja avada postkasti."},"gmailcheck_node_error":{"message":"Viga: voog vastuv\u00f5etud, kuid \u00fchtki <fullcount> s\u00f5lme ei leitud"},"gmailcheck_exception":{"message":"erand: $1","placeholders":{"1":{"content":"$1"}}}} 2 | -------------------------------------------------------------------------------- /_locales/sv/messages.json: -------------------------------------------------------------------------------- 1 | {"gmailcheck_name":{"message":"Google Mail Checker"},"gmailcheck_description":{"message":"Visar hur m\u00e5nga ol\u00e4sta meddelanden du har i inkorgen i Google Mail. Du kan ocks\u00e5 klicka p\u00e5 knappen om du vill \u00f6ppna inkorgen."},"gmailcheck_node_error":{"message":"Fel: feeden h\u00e4mtades, men ingen <fullcount>-nod hittades"},"gmailcheck_exception":{"message":"undantag: $1","placeholders":{"1":{"content":"$1"}}}} 2 | -------------------------------------------------------------------------------- /_locales/id/messages.json: -------------------------------------------------------------------------------- 1 | {"gmailcheck_name":{"message":"Google Mail Checker"},"gmailcheck_description":{"message":"Menampilkan jumlah pesan yang belum dibaca dalam kotak masuk Google Mail. Anda juga dapat mengeklik tombol ini untuk membuka kotak masuk."},"gmailcheck_node_error":{"message":"Galat: umpan diperoleh, tetapi tidak ada <fullcount> node yang ditemukan"},"gmailcheck_exception":{"message":"pengecualian: $1","placeholders":{"1":{"content":"$1"}}}} 2 | -------------------------------------------------------------------------------- /_locales/it/messages.json: -------------------------------------------------------------------------------- 1 | {"gmailcheck_name":{"message":"Google Avvisi email"},"gmailcheck_description":{"message":"Visualizza il numero di messaggi da leggere nella posta in arrivo di Google Mail. Puoi anche fare clic sul pulsante per aprire la tua posta in arrivo."},"gmailcheck_node_error":{"message":"Errore: feed recuperato ma non sono stati trovati nodi <fullcount>"},"gmailcheck_exception":{"message":"eccezione: $1","placeholders":{"1":{"content":"$1"}}}} 2 | -------------------------------------------------------------------------------- /_locales/nl/messages.json: -------------------------------------------------------------------------------- 1 | {"gmailcheck_name":{"message":"Google Mail Checker"},"gmailcheck_description":{"message":"Hiermee wordt het aantal ongelezen berichten in uw Postvak IN van Gmail weergegeven. U kunt ook op de knop klikken om het Postvak IN te openen."},"gmailcheck_node_error":{"message":"Fout: feed opgehaald, maar het knooppunt <fullcount> is niet gevonden"},"gmailcheck_exception":{"message":"uitzondering: $1","placeholders":{"1":{"content":"$1"}}}} 2 | -------------------------------------------------------------------------------- /_locales/da/messages.json: -------------------------------------------------------------------------------- 1 | {"gmailcheck_name":{"message":"Google E-mail-t\u00e6ller"},"gmailcheck_description":{"message":"Viser antallet af ul\u00e6ste meddelelser i din Google Mail-indbakke. Du kan ogs\u00e5 klikke p\u00e5 knappen for at \u00e5bne din indbakke."},"gmailcheck_node_error":{"message":"Fejl: Feedet blev hentet, men der blev ikke fundet nogen <fullcount>-node"},"gmailcheck_exception":{"message":"undtagelse: $1","placeholders":{"1":{"content":"$1"}}}} 2 | -------------------------------------------------------------------------------- /_locales/sl/messages.json: -------------------------------------------------------------------------------- 1 | {"gmailcheck_name":{"message":"Preverjevalnik za Google Mail"},"gmailcheck_description":{"message":"Prika\u017ee \u0161tevilo neprebranih sporo\u010dil v nabiralniku storitve Google Mail. Nabiralnik lahko odprete tudi s klikom gumba."},"gmailcheck_node_error":{"message":"Napaka: vir prejet, vendar ni bilo najdeno nobeno vozli\u0161\u010de <fullcount>"},"gmailcheck_exception":{"message":"izjema: $1","placeholders":{"1":{"content":"$1"}}}} 2 | -------------------------------------------------------------------------------- /_locales/fil/messages.json: -------------------------------------------------------------------------------- 1 | {"gmailcheck_name":{"message":"Google Mail Checker"},"gmailcheck_description":{"message":"Ipinapakita ang bilang ng mga hindi pa nababasang mensahe sa inbox ng iyong Google Mail. Maaari mo ring i-click ang pindutan upang buksan ang iyong inbox."},"gmailcheck_node_error":{"message":"Error: nakuha ang feed, ngunit walang <fullcount> node na natagpuan"},"gmailcheck_exception":{"message":"pagbubukod: $1","placeholders":{"1":{"content":"$1"}}}} 2 | -------------------------------------------------------------------------------- /_locales/de/messages.json: -------------------------------------------------------------------------------- 1 | {"gmailcheck_name":{"message":"Google Mail-Checker"},"gmailcheck_description":{"message":"Zeigt die Anzahl ungelesener Nachrichten in Ihrem Google Mail-Posteingang an. Sie k\u00f6nnen auch auf diese Schaltfl\u00e4che klicken, um Ihren Posteingang zu \u00f6ffnen."},"gmailcheck_node_error":{"message":"Fehler: Feed abgerufen, aber kein <fullcount> Knoten gefunden"},"gmailcheck_exception":{"message":"Ausnahme: $1","placeholders":{"1":{"content":"$1"}}}} 2 | -------------------------------------------------------------------------------- /_locales/fi/messages.json: -------------------------------------------------------------------------------- 1 | {"gmailcheck_name":{"message":"Google-s\u00e4hk\u00f6postin tarkistus"},"gmailcheck_description":{"message":"N\u00e4ytt\u00e4\u00e4, kuinka monta lukematonta viesti\u00e4 Google Mail -postilaatikossasi on. Voit my\u00f6s avata postilaatikkosi napsauttamalla painiketta."},"gmailcheck_node_error":{"message":"Virhe: sy\u00f6te haettiin, mutta <fullcount>-solmua ei l\u00f6ytynyt"},"gmailcheck_exception":{"message":"poikkeus: $1","placeholders":{"1":{"content":"$1"}}}} 2 | -------------------------------------------------------------------------------- /_locales/hr/messages.json: -------------------------------------------------------------------------------- 1 | {"gmailcheck_name":{"message":"Google Provjera po\u0161te"},"gmailcheck_description":{"message":"Prikazuje broj nepro\u010ditanih poruka u ulaznom pretincu usluge Google Mail. Mo\u017eete tako\u0111er kliknuti gumb za otvaranje ulazne po\u0161te."},"gmailcheck_node_error":{"message":"Pogre\u0161ka: Feed je dohva\u0107en, ali nije prona\u0111eno \u010dvori\u0161te <fullcount>"},"gmailcheck_exception":{"message":"izuzetak: $1","placeholders":{"1":{"content":"$1"}}}} 2 | -------------------------------------------------------------------------------- /_locales/ca/messages.json: -------------------------------------------------------------------------------- 1 | {"gmailcheck_name":{"message":"Verificador de Google Mail"},"gmailcheck_description":{"message":"Mostra el nombre de missatges no llegits que hi ha a la vostra safata d'entrada de Google Mail. Tamb\u00e9 podeu fer clic al bot\u00f3 per obrir la safata d'entrada."},"gmailcheck_node_error":{"message":"Error: s'ha recuperat el feed, per\u00f2 no s'ha trobat cap node <fullcount>"},"gmailcheck_exception":{"message":"excepci\u00f3: $1","placeholders":{"1":{"content":"$1"}}}} 2 | -------------------------------------------------------------------------------- /_locales/es_419/messages.json: -------------------------------------------------------------------------------- 1 | {"gmailcheck_name":{"message":"Google Mail Checker"},"gmailcheck_description":{"message":"Muestra el n\u00famero de mensajes sin leer en tu bandeja de entrada de Google Mail. Tambi\u00e9n puedes hacer clic en el bot\u00f3n para abrir tu bandeja de entrada."},"gmailcheck_node_error":{"message":"Error: se recuper\u00f3 el feed, pero no se encontr\u00f3 el nodo <fullcount>"},"gmailcheck_exception":{"message":"excepci\u00f3n: $1","placeholders":{"1":{"content":"$1"}}}} 2 | -------------------------------------------------------------------------------- /_locales/pt_BR/messages.json: -------------------------------------------------------------------------------- 1 | {"gmailcheck_name":{"message":"Verificador de mensagens do Google"},"gmailcheck_description":{"message":"Exibe o n\u00famero de mensagens n\u00e3o lidas na sua Caixa de entrada do Gmail. Voc\u00ea tamb\u00e9m pode clicar no bot\u00e3o para abrir a sua caixa de entrada."},"gmailcheck_node_error":{"message":"Erro: feed recuperado, mas nenhum n\u00f3 <fullcount> encontrado"},"gmailcheck_exception":{"message":"exce\u00e7\u00e3o: $1","placeholders":{"1":{"content":"$1"}}}} 2 | -------------------------------------------------------------------------------- /_locales/hu/messages.json: -------------------------------------------------------------------------------- 1 | {"gmailcheck_name":{"message":"Google Lev\u00e9lfigyel\u0151"},"gmailcheck_description":{"message":"Megjelen\u00edti az olvasatlan \u00fczeneteket a Google Mail be\u00e9rkez\u0151 levelei k\u00f6z\u00f6tt. A gombra kattintva is megnyithatja a be\u00e9rkez\u0151 leveleit."},"gmailcheck_node_error":{"message":"Hiba: h\u00edrcsatorna leh\u00edvva, de a csom\u00f3pont (<fullcount>) hi\u00e1nyzik"},"gmailcheck_exception":{"message":"kiv\u00e9tel: $1","placeholders":{"1":{"content":"$1"}}}} 2 | -------------------------------------------------------------------------------- /_locales/pt_PT/messages.json: -------------------------------------------------------------------------------- 1 | {"gmailcheck_name":{"message":"Verificador do Google Mail"},"gmailcheck_description":{"message":"Apresenta o n\u00famero de mensagens n\u00e3o lidas existentes na sua caixa de entrada do Google Mail. Pode tamb\u00e9m clicar no bot\u00e3o para abrir a caixa de entrada."},"gmailcheck_node_error":{"message":"Erro: obteve-se o feed, mas n\u00e3o foi encontrado nenhum n\u00f3 <fullcount>"},"gmailcheck_exception":{"message":"excep\u00e7\u00e3o: $1","placeholders":{"1":{"content":"$1"}}}} 2 | -------------------------------------------------------------------------------- /_locales/lv/messages.json: -------------------------------------------------------------------------------- 1 | {"gmailcheck_name":{"message":"Google Mail Checker"},"gmailcheck_description":{"message":"Tiek r\u0101d\u012bts nelas\u012bto zi\u0146ojumu skaits Google Mail ies\u016btn\u0113. Varat ar\u012b noklik\u0161\u0137in\u0101t uz pogas, lai atv\u0113rtu ies\u016btni."},"gmailcheck_node_error":{"message":"K\u013c\u016bda: pl\u016bsma ir izg\u016bta, ta\u010du netika atrasts neviens <fullcount> mezgls"},"gmailcheck_exception":{"message":"iz\u0146\u0113mums: $1","placeholders":{"1":{"content":"$1"}}}} 2 | -------------------------------------------------------------------------------- /_locales/es/messages.json: -------------------------------------------------------------------------------- 1 | {"gmailcheck_name":{"message":"Google Mail Checker"},"gmailcheck_description":{"message":"Permite ver el n\u00famero de mensajes sin leer en la bandeja de entrada de Google Mail. Tambi\u00e9n puedes hacer clic en el bot\u00f3n para abrir la bandeja de entrada."},"gmailcheck_node_error":{"message":"Se ha producido un error: el feed se ha recuperado, pero no se ha encontrado ning\u00fan nodo <fullcount>."},"gmailcheck_exception":{"message":"excepci\u00f3n: $1","placeholders":{"1":{"content":"$1"}}}} 2 | -------------------------------------------------------------------------------- /_locales/ro/messages.json: -------------------------------------------------------------------------------- 1 | {"gmailcheck_name":{"message":"Google Verificator de e-mail"},"gmailcheck_description":{"message":"Afi\u015feaz\u0103 num\u0103rul mesajelor necitite din folderul Mesaje primite al contului Google Mail. De asemenea, pute\u0163i s\u0103 face\u0163i clic pe buton pentru a deschide folderul Mesaje primite."},"gmailcheck_node_error":{"message":"Eroare: s-a preluat feedul, dar nu s-a g\u0103sit niciun nod <fullcount>"},"gmailcheck_exception":{"message":"excep\u0163ie: $1","placeholders":{"1":{"content":"$1"}}}} 2 | -------------------------------------------------------------------------------- /_locales/cs/messages.json: -------------------------------------------------------------------------------- 1 | {"gmailcheck_name":{"message":"Kontrola e-mailu Google"},"gmailcheck_description":{"message":"Zobraz\u00ed po\u010det nep\u0159e\u010dten\u00fdch zpr\u00e1v ve slo\u017ece Doru\u010den\u00e1 po\u0161ta slu\u017eby Google Mail. Kliknut\u00edm na tla\u010d\u00edtko tuto slo\u017eku otev\u0159ete."},"gmailcheck_node_error":{"message":"Chyba: Zdroj byl na\u010dten, nebyl v\u0161ak nalezen \u017e\u00e1dn\u00fd uzel <fullcount>."},"gmailcheck_exception":{"message":"v\u00fdjimka: $1","placeholders":{"1":{"content":"$1"}}}} 2 | -------------------------------------------------------------------------------- /_locales/pl/messages.json: -------------------------------------------------------------------------------- 1 | {"gmailcheck_name":{"message":"Sprawdzanie poczty Google"},"gmailcheck_description":{"message":"Wy\u015bwietla liczb\u0119 nieprzeczytanych wiadomo\u015bci w Twojej skrzynce odbiorczej Google Mail. Mo\u017cesz te\u017c klikn\u0105\u0107 przycisk, aby otworzy\u0107 swoj\u0105 skrzynk\u0119 odbiorcz\u0105."},"gmailcheck_node_error":{"message":"B\u0142\u0105d: pobrano kana\u0142, ale nie odnaleziono w\u0119z\u0142a <fullcount>"},"gmailcheck_exception":{"message":"wyj\u0105tek: $1","placeholders":{"1":{"content":"$1"}}}} 2 | -------------------------------------------------------------------------------- /_locales/tr/messages.json: -------------------------------------------------------------------------------- 1 | {"gmailcheck_name":{"message":"Google Mail Checker"},"gmailcheck_description":{"message":"Google Mail gelen kutunuzdaki okunmam\u0131\u015f iletilerin say\u0131s\u0131n\u0131 g\u00f6r\u00fcnt\u00fcler. Ayr\u0131ca, d\u00fc\u011fmeyi t\u0131klayarak gelen kutunuzu da a\u00e7abilirsiniz."},"gmailcheck_node_error":{"message":"Hata: yay\u0131n al\u0131nd\u0131, ancak <fullcount> d\u00fc\u011f\u00fcm\u00fc bulunamad\u0131"},"gmailcheck_exception":{"message":"\u00f6zel durum: $1","placeholders":{"1":{"content":"$1"}}}} 2 | -------------------------------------------------------------------------------- /_locales/fr/messages.json: -------------------------------------------------------------------------------- 1 | {"gmailcheck_name":{"message":"V\u00e9rificateur de messages Google"},"gmailcheck_description":{"message":"Affiche le nombre de messages non lus dans votre bo\u00eete de r\u00e9ception Google\u00a0Mail. Vous avez \u00e9galement la possibilit\u00e9 de cliquer sur ce bouton pour ouvrir cette derni\u00e8re."},"gmailcheck_node_error":{"message":"Erreur\u00a0: flux r\u00e9cup\u00e9r\u00e9, mais aucun n\u0153ud <fullcount> trouv\u00e9"},"gmailcheck_exception":{"message":"exception\u00a0: $1","placeholders":{"1":{"content":"$1"}}}} 2 | -------------------------------------------------------------------------------- /_locales/zh_CN/messages.json: -------------------------------------------------------------------------------- 1 | {"gmailcheck_name":{"message":"Google Mail Checker"},"gmailcheck_description":{"message":"\u663e\u793a Google Mail \u6536\u4ef6\u7bb1\u4e2d\u7684\u672a\u8bfb\u90ae\u4ef6\u6570\u3002\u70b9\u51fb\u8be5\u6309\u94ae\u8fd8\u53ef\u4ee5\u6253\u5f00\u60a8\u7684\u6536\u4ef6\u7bb1\u3002"},"gmailcheck_node_error":{"message":"\u9519\u8bef\uff1a\u7cfb\u7edf\u5df2\u68c0\u7d22\u4f9b\u7a3f\uff0c\u4f46\u672a\u53d1\u73b0 <fullcount> \u8282\u70b9"},"gmailcheck_exception":{"message":"\u5f02\u5e38\uff1a$1","placeholders":{"1":{"content":"$1"}}}} 2 | -------------------------------------------------------------------------------- /_locales/zh_TW/messages.json: -------------------------------------------------------------------------------- 1 | {"gmailcheck_name":{"message":"Google Mail Checker"},"gmailcheck_description":{"message":"\u5728 Google Mail \u6536\u4ef6\u5323\u4e2d\u986f\u793a\u672a\u8b80\u90f5\u4ef6\u7684\u6578\u76ee\u3002\u6309\u4e00\u4e0b\u6309\u9215\u4e5f\u53ef\u4ee5\u958b\u555f\u6536\u4ef6\u5323\u3002"},"gmailcheck_node_error":{"message":"\u932f\u8aa4\uff1a\u64f7\u53d6\u5230\u8cc7\u8a0a\u63d0\u4f9b\uff0c\u4f46\u627e\u4e0d\u5230 <fullcount> \u7bc0\u9ede"},"gmailcheck_exception":{"message":"\u4f8b\u5916\u72c0\u6cc1\uff1a$1","placeholders":{"1":{"content":"$1"}}}} 2 | -------------------------------------------------------------------------------- /_locales/sk/messages.json: -------------------------------------------------------------------------------- 1 | {"gmailcheck_name":{"message":"Kontrola po\u0161ty Google"},"gmailcheck_description":{"message":"Zobraz\u00ed po\u010det nepre\u010d\u00edtan\u00fdch spr\u00e1v v prie\u010dinku doru\u010denej po\u0161ty v slu\u017ebe Gmail. Kliknut\u00edm na tla\u010didlo prie\u010dinok doru\u010denej po\u0161ty otvor\u00edte."},"gmailcheck_node_error":{"message":"Chyba: informa\u010dn\u00fd kan\u00e1l bol na\u010d\u00edtan\u00fd, nena\u0161iel sa v\u0161ak \u017eiadny uzol <fullcount>."},"gmailcheck_exception":{"message":"v\u00fdnimka: $1","placeholders":{"1":{"content":"$1"}}}} 2 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | // Enforcing options 3 | "camelcase": true, 4 | "curly": true, 5 | "eqeqeq": true, 6 | "forin": true, 7 | "freeze": true, 8 | "immed": true, 9 | "indent": 2, 10 | "latedef": true, 11 | "newcap": true, 12 | "noarg": true, 13 | "noempty": true, 14 | "nonbsp": true, 15 | "quotmark": "single", 16 | "undef": true, 17 | "unused": "vars", 18 | 19 | // Relaxing options 20 | "eqnull": true, 21 | "multistr": true, 22 | 23 | // Environments 24 | "browser": true, 25 | 26 | "globals": { 27 | "console": true, 28 | "chrome": true 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /_locales/lt/messages.json: -------------------------------------------------------------------------------- 1 | {"gmailcheck_name":{"message":"\u201eGoogle\u201c pa\u0161to tikrintuvas"},"gmailcheck_description":{"message":"Pateikiamas \u201eGoogle\u201c pa\u0161to gaut\u0173 lai\u0161k\u0173 aplanke esan\u010di\u0173 neperskaityt\u0173 prane\u0161im\u0173 skai\u010dius. Be to, jei norite atidaryti gaut\u0173 lai\u0161k\u0173 aplank\u0105, galite spustel\u0117ti mygtuk\u0105."},"gmailcheck_node_error":{"message":"Klaida: sklaidos kanalas nuskaitytas, ta\u010diau nerastas joks <fullcount> mazgas"},"gmailcheck_exception":{"message":"i\u0161imtis: $1","placeholders":{"1":{"content":"$1"}}}} 2 | -------------------------------------------------------------------------------- /_locales/ko/messages.json: -------------------------------------------------------------------------------- 1 | {"gmailcheck_name":{"message":"Google Mail Checker"},"gmailcheck_description":{"message":"Gmaill \ubc1b\uc740\ud3b8\uc9c0\ud568\uc5d0\uc11c \uc77d\uc9c0 \uc54a\uc740 \uba54\uc77c\uc758 \uc218\ub97c \ub098\ud0c0\ub0c5\ub2c8\ub2e4. \ub610\ud55c \ubc84\ud2bc\uc744 \ud074\ub9ad\ud558\uc5ec \ubc1b\uc740\ud3b8\uc9c0\ud568\uc744 \uc5f4 \uc218\ub3c4 \uc788\uc2b5\ub2c8\ub2e4."},"gmailcheck_node_error":{"message":"\uc624\ub958: \ud53c\ub4dc\ub97c \uac80\uc0c9\ud588\uc73c\ub098 \ucd1d <fullcount>\uac1c\uc758 \ub178\ub4dc\ub97c \ucc3e\uc9c0 \ubabb\ud588\uc2b5\ub2c8\ub2e4."},"gmailcheck_exception":{"message":"\uc608\uc678: $1","placeholders":{"1":{"content":"$1"}}}} 2 | -------------------------------------------------------------------------------- /AUTHORS.md: -------------------------------------------------------------------------------- 1 | Authors 2 | ======= 3 | 4 | [Inbox by Gmail Checker][home] is written and maintained by Joe Esposito, 5 | along with the following contributors: 6 | 7 | - James Neal ([@james0x0A](https://github.com/james0x0A)) 8 | - Amelia Michlig ([@michliga](https://github.com/michliga)) 9 | - Daniel Peukert ([@dpeukert](https://github.com/dpeukert)) 10 | - Davit ([@davo11122](https://github.com/davo11122)) 11 | - Robert Orzanna ([@orschiro](https://github.com/orschiro)) 12 | - ShaLi Shaltiel ([@shali3](https://github.com/shali3)) 13 | - Nikodem Ośmiałowski ([@Najki](https://github.com/Najki)) 14 | - Carlos Cabral ([@CarlosHBC](https://github.com/CarlosHBC)) 15 | 16 | 17 | [home]: README.md 18 | -------------------------------------------------------------------------------- /_locales/ja/messages.json: -------------------------------------------------------------------------------- 1 | {"gmailcheck_name":{"message":"Google Mail Checker"},"gmailcheck_description":{"message":"Google Mail \u306e\u53d7\u4fe1\u30c8\u30ec\u30a4\u306b\u3042\u308b\u672a\u8aad\u306e\u30e1\u30fc\u30eb\u6570\u3092\u8868\u793a\u3057\u307e\u3059\u3002\u3053\u306e\u30dc\u30bf\u30f3\u3092\u30af\u30ea\u30c3\u30af\u3057\u3066\u53d7\u4fe1\u30c8\u30ec\u30a4\u3092\u958b\u304f\u3053\u3068\u3082\u3067\u304d\u307e\u3059\u3002"},"gmailcheck_node_error":{"message":"\u30a8\u30e9\u30fc: \u53d6\u5f97\u3057\u305f\u30d5\u30a3\u30fc\u30c9\u306b <fullcount> \u30ce\u30fc\u30c9\u304c\u3042\u308a\u307e\u305b\u3093"},"gmailcheck_exception":{"message":"\u4f8b\u5916: $1","placeholders":{"1":{"content":"$1"}}}} 2 | -------------------------------------------------------------------------------- /_locales/vi/messages.json: -------------------------------------------------------------------------------- 1 | {"gmailcheck_name":{"message":"Tr\u00ecnh Ki\u1ec3m tra Th\u01b0 c\u1ee7a Google"},"gmailcheck_description":{"message":"Hi\u1ec3n th\u1ecb s\u1ed1 th\u01b0 ch\u01b0a \u0111\u1ecdc trong h\u1ed9p th\u01b0 \u0111\u1ebfn Gmail c\u1ee7a b\u1ea1n. B\u1ea1n c\u0169ng c\u00f3 th\u1ec3 nh\u1ea5p v\u00e0o n\u00fat \u0111\u1ec3 m\u1edf h\u1ed9p th\u01b0 \u0111\u1ebfn c\u1ee7a m\u00ecnh."},"gmailcheck_node_error":{"message":"L\u1ed7i: ngu\u1ed3n c\u1ea5p d\u1eef li\u1ec7u \u0111\u00e3 \u0111\u01b0\u1ee3c truy xu\u1ea5t nh\u01b0ng kh\u00f4ng t\u00ecm th\u1ea5y n\u00fat <fullcount> n\u00e0o"},"gmailcheck_exception":{"message":"ngo\u1ea1i l\u1ec7: $1","placeholders":{"1":{"content":"$1"}}}} 2 | -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "manifest_version": 2, 3 | "name": "Inbox by Gmail Checker", 4 | "version": "4.3.0", 5 | "description": "Displays the number of unread messages in your Inbox by Gmail. You can also click the button to open your inbox.", 6 | "author": "Joe Esposito ", 7 | "icons": { 8 | "128": "media/icon_128.png", 9 | "256": "media/icon_256.png" 10 | }, 11 | "browser_action": { 12 | "default_icon": "media/inbox_not_logged_in.png" 13 | }, 14 | "background": { 15 | "persistent": false, 16 | "page": "background.html" 17 | }, 18 | "options_page": "options.html", 19 | "optional_permissions": ["tabs"], 20 | "permissions": [ 21 | "alarms", 22 | "activeTab", 23 | "contextMenus", 24 | "storage", 25 | "notifications", 26 | "*://inbox.google.com/", 27 | "*://mail.google.com/" 28 | ], 29 | "default_locale": "en" 30 | } 31 | -------------------------------------------------------------------------------- /_locales/he/messages.json: -------------------------------------------------------------------------------- 1 | {"gmailcheck_name":{"message":"Google Mail Checker"},"gmailcheck_description":{"message":"\u05de\u05e6\u05d9\u05d2 \u05d0\u05ea \u05de\u05e1\u05e4\u05e8 \u05d4\u05d4\u05d5\u05d3\u05e2\u05d5\u05ea \u05e9\u05dc\u05d0 \u05e0\u05e7\u05e8\u05d0\u05d5 \u05d1\u05ea\u05d9\u05d1\u05ea \u05d4\u05d3\u05d5\u05d0\u05e8 \u05d4\u05e0\u05db\u05e0\u05e1 \u05e9\u05dc\u05da \u05d1-Google Mail. \u05d1\u05e0\u05d5\u05e1\u05e3, \u05ea\u05d5\u05db\u05dc \u05dc\u05dc\u05d7\u05d5\u05e5 \u05e2\u05dc \u05d4\u05dc\u05d7\u05e6\u05df \u05db\u05d3\u05d9 \u05dc\u05e4\u05ea\u05d5\u05d7 \u05d0\u05ea \u05ea\u05d9\u05d1\u05ea \u05d4\u05d3\u05d5\u05d0\u05e8 \u05d4\u05e0\u05db\u05e0\u05e1."},"gmailcheck_node_error":{"message":"\u05e9\u05d2\u05d9\u05d0\u05d4: \u05d4\u05e2\u05d3\u05db\u05d5\u05df \u05d0\u05d5\u05d7\u05d6\u05e8, \u05d0\u05da \u05dc\u05d0 \u05e0\u05de\u05e6\u05d0\u05d5 \u05e6\u05de\u05ea\u05d9\u05dd \u05e9\u05dc <fullcount>"},"gmailcheck_exception":{"message":"\u05d7\u05e8\u05d9\u05d2: $1","placeholders":{"1":{"content":"$1"}}}} 2 | -------------------------------------------------------------------------------- /_locales/ar/messages.json: -------------------------------------------------------------------------------- 1 | {"gmailcheck_name":{"message":"Google Mail Checker"},"gmailcheck_description":{"message":"\u0644\u0639\u0631\u0636 \u0639\u062f\u062f \u0627\u0644\u0631\u0633\u0627\u0626\u0644 \u063a\u064a\u0631 \u0627\u0644\u0645\u0642\u0631\u0648\u0621\u0629 \u0641\u064a \u0627\u0644\u0628\u0631\u064a\u062f \u0627\u0644\u0648\u0627\u0631\u062f \u0641\u064a Google Mail. \u0643\u0645\u0627 \u064a\u0645\u0643\u0646\u0643 \u0627\u0644\u0646\u0642\u0631 \u0639\u0644\u0649 \u0627\u0644\u0632\u0631 \u0644\u0641\u062a\u062d \u0628\u0631\u064a\u062f\u0643 \u0627\u0644\u0648\u0627\u0631\u062f."},"gmailcheck_node_error":{"message":"\u062e\u0637\u0623: \u062a\u0645 \u0627\u0633\u062a\u0631\u062f\u0627\u062f \u0627\u0644\u062e\u0644\u0627\u0635\u0629\u060c \u0648\u0644\u0643\u0646 \u0644\u0645 \u064a\u062a\u0645 \u0627\u0644\u0639\u062b\u0648\u0631 \u0639\u0644\u0649 <fullcount> \u0645\u0646 \u0627\u0644\u0639\u064f\u0642\u062f"},"gmailcheck_exception":{"message":"\u0627\u0633\u062a\u062b\u0646\u0627\u0621: $1","placeholders":{"1":{"content":"$1"}}}} 2 | -------------------------------------------------------------------------------- /_locales/sr/messages.json: -------------------------------------------------------------------------------- 1 | {"gmailcheck_name":{"message":"Google \u043f\u0440\u043e\u0432\u0435\u0440\u0430 \u043f\u043e\u0448\u0442\u0435"},"gmailcheck_description":{"message":"\u041f\u0440\u0438\u043a\u0430\u0437\u0443\u0458\u0435 \u0431\u0440\u043e\u0458 \u043d\u0435\u043f\u0440\u043e\u0447\u0438\u0442\u0430\u043d\u0438\u0445 \u043f\u0440\u0438\u043c\u0459\u0435\u043d\u0438\u0445 \u043f\u043e\u0440\u0443\u043a\u0430 Google Mail-\u0430. \u041c\u043e\u0436\u0435\u0442\u0435 \u0438 \u0434\u0430 \u043a\u043b\u0438\u043a\u043d\u0435\u0442\u0435 \u043d\u0430 \u0434\u0443\u0433\u043c\u0435 \u0438 \u043e\u0442\u0432\u043e\u0440\u0438\u0442\u0435 \u043f\u0440\u0438\u043c\u0459\u0435\u043d\u0435 \u043f\u043e\u0440\u0443\u043a\u0435."},"gmailcheck_node_error":{"message":"\u0413\u0440\u0435\u0448\u043a\u0430: \u0424\u0438\u0434 \u0458\u0435 \u043f\u0440\u0435\u0443\u0437\u0435\u0442, \u0430\u043b\u0438 \u0447\u0432\u043e\u0440 <fullcount> \u043d\u0438\u0458\u0435 \u043f\u0440\u043e\u043d\u0430\u0452\u0435\u043d"},"gmailcheck_exception":{"message":"\u0438\u0437\u0443\u0437\u0435\u0442\u0430\u043a: $1","placeholders":{"1":{"content":"$1"}}}} 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014-2017 Joe Esposito 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /_locales/th/messages.json: -------------------------------------------------------------------------------- 1 | {"gmailcheck_name":{"message":"Google Mail Checker"},"gmailcheck_description":{"message":"\u0e41\u0e2a\u0e14\u0e07\u0e08\u0e33\u0e19\u0e27\u0e19\u0e02\u0e2d\u0e07\u0e02\u0e49\u0e2d\u0e04\u0e27\u0e32\u0e21\u0e17\u0e35\u0e48\u0e22\u0e31\u0e07\u0e44\u0e21\u0e48\u0e44\u0e14\u0e49\u0e2d\u0e48\u0e32\u0e19\u0e43\u0e19\u0e01\u0e25\u0e48\u0e2d\u0e07\u0e08\u0e14\u0e2b\u0e21\u0e32\u0e22 Google Mail \u0e02\u0e2d\u0e07\u0e04\u0e38\u0e13 \u0e41\u0e25\u0e30\u0e04\u0e38\u0e13\u0e2a\u0e32\u0e21\u0e32\u0e23\u0e16\u0e04\u0e25\u0e34\u0e01\u0e1b\u0e38\u0e48\u0e21\u0e40\u0e1e\u0e37\u0e48\u0e2d\u0e40\u0e1b\u0e34\u0e14\u0e01\u0e25\u0e48\u0e2d\u0e07\u0e08\u0e14\u0e2b\u0e21\u0e32\u0e22\u0e02\u0e2d\u0e07\u0e04\u0e38\u0e13\u0e44\u0e14\u0e49\u0e40\u0e0a\u0e48\u0e19\u0e01\u0e31\u0e19"},"gmailcheck_node_error":{"message":"\u0e02\u0e49\u0e2d\u0e1c\u0e34\u0e14\u0e1e\u0e25\u0e32\u0e14: \u0e40\u0e23\u0e35\u0e22\u0e01\u0e04\u0e37\u0e19\u0e1f\u0e35\u0e14\u0e41\u0e25\u0e49\u0e27 \u0e41\u0e15\u0e48\u0e44\u0e21\u0e48\u0e1e\u0e1a\u0e42\u0e2b\u0e19\u0e14 <fullcount>"},"gmailcheck_exception":{"message":"\u0e02\u0e49\u0e2d\u0e22\u0e01\u0e40\u0e27\u0e49\u0e19: $1","placeholders":{"1":{"content":"$1"}}}} 2 | -------------------------------------------------------------------------------- /_locales/ru/messages.json: -------------------------------------------------------------------------------- 1 | {"gmailcheck_name":{"message":"Google Mail Checker"},"gmailcheck_description":{"message":"\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u043d\u0435\u043f\u0440\u043e\u0447\u0438\u0442\u0430\u043d\u043d\u044b\u0445 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u0432 \u043f\u043e\u0447\u0442\u043e\u0432\u043e\u043c \u044f\u0449\u0438\u043a\u0435 Google Mail. \u041c\u043e\u0436\u043d\u043e \u0442\u0430\u043a\u0436\u0435 \u043d\u0430\u0436\u0430\u0442\u044c \u043a\u043d\u043e\u043f\u043a\u0443, \u0447\u0442\u043e\u0431\u044b \u043e\u0442\u043a\u0440\u044b\u0442\u044c \u043f\u0430\u043f\u043a\u0443 \"\u0412\u0445\u043e\u0434\u044f\u0449\u0438\u0435\"."},"gmailcheck_node_error":{"message":"\u041e\u0448\u0438\u0431\u043a\u0430: \u0444\u0438\u0434 \u0431\u044b\u043b \u043f\u043e\u043b\u0443\u0447\u0435\u043d, \u043d\u043e \u043d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043d\u0430\u0439\u0442\u0438 \u0443\u0437\u0435\u043b <fullcount>"},"gmailcheck_exception":{"message":"\u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435: $1","placeholders":{"1":{"content":"$1"}}}} 2 | -------------------------------------------------------------------------------- /_locales/hi/messages.json: -------------------------------------------------------------------------------- 1 | {"gmailcheck_name":{"message":"Google \u092e\u0947\u0932 \u091c\u093e\u0902\u091a\u0915\u0930\u094d\u0924\u093e"},"gmailcheck_description":{"message":"\u0906\u092a\u0915\u0947 Google \u092e\u0947\u0932 \u0907\u0928\u092c\u0949\u0915\u094d\u0938 \u092e\u0947\u0902 \u0928 \u092a\u095d\u0947 \u0917\u090f \u0938\u0902\u0926\u0947\u0936\u094b\u0902 \u0915\u0940 \u0938\u0902\u0916\u094d\u092f\u093e \u092a\u094d\u0930\u0926\u0930\u094d\u0936\u093f\u0924 \u0915\u0930\u0924\u093e \u0939\u0948. \u0906\u092a \u0905\u092a\u0928\u093e \u0907\u0928\u092c\u0949\u0915\u094d\u0938 \u0916\u094b\u0932\u0928\u0947 \u0915\u0947 \u0932\u093f\u090f \u092c\u091f\u0928 \u0915\u094d\u0932\u093f\u0915 \u092d\u0940 \u0915\u0930 \u0938\u0915\u0924\u0947 \u0939\u0948\u0902."},"gmailcheck_node_error":{"message":"\u0924\u094d\u0930\u0941\u091f\u093f: \u095e\u0940\u0921 \u092a\u0941\u0928\u0930\u094d\u092a\u094d\u0930\u093e\u092a\u094d\u0924 \u0915\u0940 \u0917\u0908, \u0932\u0947\u0915\u093f\u0928 \u0915\u094b\u0908 <fullcount> \u0928\u094b\u0921 \u0928\u0939\u0940\u0902 \u092e\u093f\u0932\u093e"},"gmailcheck_exception":{"message":"\u0905\u092a\u0935\u093e\u0926: $1","placeholders":{"1":{"content":"$1"}}}} 2 | -------------------------------------------------------------------------------- /_locales/bg/messages.json: -------------------------------------------------------------------------------- 1 | {"gmailcheck_name":{"message":"Google \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u0430 \u043f\u043e\u0449\u0430\u0442\u0430"},"gmailcheck_description":{"message":"\u041f\u043e\u043a\u0430\u0437\u0432\u0430 \u0431\u0440\u043e\u044f \u043d\u0435\u043f\u0440\u043e\u0447\u0435\u0442\u0435\u043d\u0438 \u0441\u044a\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0432\u044a\u0432 \u0432\u0445\u043e\u0434\u044f\u0449\u0430\u0442\u0430 \u0432\u0438 \u043f\u043e\u0449\u0430 \u0432 Google Mail. \u041c\u043e\u0436\u0435\u0442\u0435 \u0441\u044a\u0449\u043e \u0434\u0430 \u043a\u043b\u0438\u043a\u043d\u0435\u0442\u0435 \u0432\u044a\u0440\u0445\u0443 \u0431\u0443\u0442\u043e\u043d\u0430, \u0437\u0430 \u0434\u0430 \u044f \u043e\u0442\u0432\u043e\u0440\u0438\u0442\u0435."},"gmailcheck_node_error":{"message":"\u0413\u0440\u0435\u0448\u043a\u0430: \u0415\u043c\u0438\u0441\u0438\u044f\u0442\u0430 \u0431\u0435 \u0438\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0430, \u043d\u043e \u043d\u044f\u043c\u0430 \u043d\u0430\u043c\u0435\u0440\u0435\u043d \u0432\u044a\u0437\u0435\u043b <fullcount>"},"gmailcheck_exception":{"message":"\u0438\u0437\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435: $1","placeholders":{"1":{"content":"$1"}}}} 2 | -------------------------------------------------------------------------------- /_locales/el/messages.json: -------------------------------------------------------------------------------- 1 | {"gmailcheck_name":{"message":"\u0388\u03bb\u03b5\u03b3\u03c7\u03bf\u03c2 \u03c4\u03bf\u03c5 Google Mail"},"gmailcheck_description":{"message":"\u0395\u03bc\u03c6\u03b1\u03bd\u03af\u03b6\u03b5\u03b9 \u03c4\u03bf\u03bd \u03b1\u03c1\u03b9\u03b8\u03bc\u03cc \u03c4\u03c9\u03bd \u03bc\u03b7 \u03b1\u03bd\u03b1\u03b3\u03bd\u03c9\u03c3\u03bc\u03ad\u03bd\u03c9\u03bd \u03bc\u03b7\u03bd\u03c5\u03bc\u03ac\u03c4\u03c9\u03bd \u03c3\u03c4\u03b1 \u03b5\u03b9\u03c3\u03b5\u03c1\u03c7\u03cc\u03bc\u03b5\u03bd\u03b1 \u03c4\u03bf\u03c5 Google Mail \u03c3\u03b1\u03c2. \u039c\u03c0\u03bf\u03c1\u03b5\u03af\u03c4\u03b5 \u03b5\u03c0\u03af\u03c3\u03b7\u03c2 \u03bd\u03b1 \u03ba\u03ac\u03bd\u03b5\u03c4\u03b5 \u03ba\u03bb\u03b9\u03ba \u03c3\u03c4\u03bf \u03ba\u03bf\u03c5\u03bc\u03c0\u03af \u03b3\u03b9\u03b1 \u03bd\u03b1 \u03b1\u03bd\u03bf\u03af\u03be\u03b5\u03c4\u03b5 \u03c4\u03b1 \u03b5\u03b9\u03c3\u03b5\u03c1\u03c7\u03cc\u03bc\u03b5\u03bd\u03ac \u03c3\u03b1\u03c2."},"gmailcheck_node_error":{"message":"\u03a3\u03c6\u03ac\u03bb\u03bc\u03b1: \u03ad\u03b3\u03b9\u03bd\u03b5 \u03b1\u03bd\u03ac\u03ba\u03c4\u03b7\u03c3\u03b7 \u03c1\u03bf\u03ae\u03c2, \u03b1\u03bb\u03bb\u03ac \u03b4\u03b5\u03bd \u03b2\u03c1\u03ad\u03b8\u03b7\u03ba\u03b5 \u03ba\u03cc\u03bc\u03b2\u03bf\u03c2 <fullcount>"},"gmailcheck_exception":{"message":"\u03b5\u03be\u03b1\u03af\u03c1\u03b5\u03c3\u03b7: $1","placeholders":{"1":{"content":"$1"}}}} 2 | -------------------------------------------------------------------------------- /_locales/uk/messages.json: -------------------------------------------------------------------------------- 1 | {"gmailcheck_name":{"message":"\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0430 \u043f\u043e\u0448\u0442\u0438 Google"},"gmailcheck_description":{"message":"\u0412\u0456\u0434\u043e\u0431\u0440\u0430\u0436\u0430\u0454 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u043d\u0435\u043f\u0440\u043e\u0447\u0438\u0442\u0430\u043d\u0438\u0445 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u044c \u0443 \u043f\u0430\u043f\u0446\u0456 \u0437 \u0432\u0445\u0456\u0434\u043d\u0438\u043c\u0438 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f\u043c\u0438 \u0441\u043b\u0443\u0436\u0431\u0438 Google Mail. \u0429\u043e\u0431 \u0432\u0456\u0434\u043a\u0440\u0438\u0442\u0438 \u043f\u0430\u043f\u043a\u0443 \u0437 \u0432\u0445\u0456\u0434\u043d\u0438\u043c\u0438 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f\u043c\u0438, \u043c\u043e\u0436\u043d\u0430 \u0442\u0430\u043a\u043e\u0436 \u043d\u0430\u0442\u0438\u0441\u043d\u0443\u0442\u0438 \u0446\u044e \u043a\u043d\u043e\u043f\u043a\u0443."},"gmailcheck_node_error":{"message":"\u041f\u043e\u043c\u0438\u043b\u043a\u0430: \u043a\u0430\u043d\u0430\u043b \u0432\u0456\u0434\u043d\u043e\u0432\u043b\u0435\u043d\u043e, \u0430\u043b\u0435 \u0436\u043e\u0434\u043d\u043e\u0433\u043e \u0432\u0443\u0437\u043b\u0430 <fullcount> \u043d\u0435 \u0437\u043d\u0430\u0439\u0434\u0435\u043d\u043e"},"gmailcheck_exception":{"message":"\u0432\u0438\u043d\u044f\u0442\u043e\u043a: $1","placeholders":{"1":{"content":"$1"}}}} 2 | -------------------------------------------------------------------------------- /options.css: -------------------------------------------------------------------------------- 1 | body { 2 | background: #eee; 3 | color: #333; 4 | font-size: 14px; 5 | } 6 | h1 { 7 | margin-top: 0; 8 | } 9 | form { 10 | display: block; 11 | padding: 12px 0; 12 | } 13 | section { 14 | display: block; 15 | background: white; 16 | border: 1px solid #ccc; 17 | border-radius: 3px; 18 | margin: 12px auto 12px auto; 19 | padding: 12px 32px; 20 | width: 704px; 21 | } 22 | footer { 23 | display: block; 24 | margin: 0 auto; 25 | width: 768px; 26 | color: #555; 27 | } 28 | footer a { 29 | color: #555; 30 | } 31 | .clearfix { 32 | clear: both; 33 | } 34 | .pull-right { 35 | float: right; 36 | } 37 | .secondary { 38 | background: #f8f8f8; 39 | } 40 | .symbol { 41 | color: #777; 42 | } 43 | .form-group { 44 | display: block; 45 | padding: 8px; 46 | margin: 0; 47 | } 48 | .form-group .inline-input { 49 | margin-left: 4px; 50 | } 51 | .form-group .option { 52 | width: 200px; 53 | display: inline-block; 54 | vertical-align: top; 55 | } 56 | .form-group .help-text { 57 | margin-left: 32px; 58 | display: inline-block; 59 | max-width: 450px; 60 | } 61 | .form-group .help-text.multiline { 62 | vertical-align: bottom; 63 | } 64 | .default-user-control { 65 | width: 84px; 66 | text-align: left; 67 | } 68 | .default-user-control.large { 69 | margin-top: 4px; 70 | width: 194px; 71 | text-align: left; 72 | } 73 | .btn { 74 | padding: 6px 24px; 75 | margin-right: 12px; 76 | } 77 | .status { 78 | display: inline-block; 79 | font-size: 16px; 80 | color: green; 81 | } 82 | .status.error { 83 | font-size: 14px; 84 | color: red; 85 | } 86 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Inbox by Gmail Checker 2 | ====================== 3 | 4 | ![Current version on the Chrome Web Store](https://img.shields.io/badge/chrome%20web%20store-4.3.0-blue.svg "Current version on the Chrome Web Store") 5 | ![Rating on the Chrome Web Store](https://img.shields.io/badge/rating-%E2%98%85%E2%98%85%E2%98%85%E2%98%85%E2%98%86%204.4%20(178%20votes)-brightgreen.svg "Rating on the Chrome Web Store") 6 | 7 | Displays the number of unread messages in Inbox by Gmail. You can also click the button to open your inbox and receive notifications on new email. You can set "quiet hours" to eliminate distraction during your most productive hours or temporarily go "distraction free" for a pomodoro-like experience. 8 | 9 | This is a derivative work of the [Google Mail Checker][] to work with Inbox by Gmail. 10 | 11 | ![Screenshot](media/screenshot.png) 12 | 13 | 14 | Features 15 | -------- 16 | 17 | - Displays the unread count directly on the icon 18 | - Click the icon to open your inbox in a new tab 19 | - Set which account to use when signed into multiple Google accounts 20 | - Optionally **set quiet hours** to hide the unread count during your peak productivity time 21 | 22 | 23 | Installation 24 | ------------ 25 | 26 | ![Try it now](media/tryitnowbutton.png "Click here to install from the Chrome Web Store") 27 | 28 | Or manually: 29 | 30 | 1. Download or `git clone http://github.com/joeyespo/inbox-by-gmail-checker.git` 31 | 2. Open Chrome extensions and click on the `Load unpacked extension` button 32 | 3. Select the downloaded directory 33 | 34 | 35 | Contributing 36 | ------------ 37 | 38 | 1. Check the open issues or open a new issue to start a discussion around 39 | your feature idea or the bug you found 40 | 2. Fork the repository, make your changes, and add yourself to [authors.md][] 41 | 3. Send a pull request 42 | 43 | If your PR has been waiting a while, feel free to [ping me on Twitter](http://twitter.com/joeyespo). 44 | 45 | 46 | [google mail checker]: http://developer.chrome.com/extensions/samples#google-mail-checker 47 | [authors.md]: AUTHORS.md 48 | -------------------------------------------------------------------------------- /CHANGES.md: -------------------------------------------------------------------------------- 1 | Inbox by Gmail Checker Changelog 2 | -------------------------------- 3 | 4 | 5 | #### Development 6 | 7 | - Cleanup: Move images to `media/` 8 | - Readme: Fix badges 9 | 10 | 11 | #### Version 4.3.0 (2017-06-21) 12 | 13 | - Enhancement: Add "Share page via email" extension and optional page context menus ([#25](https://github.com/joeyespo/inbox-by-gmail-checker/issues/25)) 14 | - Enhancement: Add [Pomodoro](https://en.wikipedia.org/wiki/Pomodoro_Technique)-inspired "Distraction-free mode" 15 | - Enhancement: Show current version on options page 16 | - Enhancement: Make "tabs" permission optional with a new "focus existing Inbox tab" option 17 | - Enhancement: Remove unnecessary permissions ([#25](https://github.com/joeyespo/inbox-by-gmail-checker/issues/25)) 18 | - Bugfix: Do nothing if current tab is already Inbox 19 | - Bugfix: Open login page only once on disconnect 20 | - Readme: Add a description of the extension 21 | - Clarify option descriptions 22 | - Cleanup 23 | 24 | 25 | #### Version 4.2.0 (2017-02-27) 26 | 27 | - Enhancement: Require only Gmail and Inbox permissions instead of all Google apps ([#24](https://github.com/joeyespo/inbox-by-gmail-checker/pull/24) - thanks, [@Najki][]!) 28 | - Enhancement: Optimize all images losslessly ([#22](https://github.com/joeyespo/inbox-by-gmail-checker/pull/22) - thanks, [@CarlosHBC][]!) 29 | 30 | 31 | #### Version 4.1.0 (2017-02-26) 32 | 33 | - Enhancement: Focus or open Inbox when the notification is clicked 34 | - Enhancement: Set default poll interval to 3 seconds instead of a minute 35 | - Bugfix: Do not open a new Inbox tab when focusing an existing one ([#21](https://github.com/joeyespo/inbox-by-gmail-checker/pull/21) - thanks, [@shali3][]!) 36 | - Bugfix: Focus an existing Inbox tab only within the current window 37 | - Bugfix: Do not show notifications during quiet hours 38 | 39 | 40 | #### Version 4.0.0 (2017-02-26) 41 | 42 | - Enhancement: Add new mail notifications ([#18](https://github.com/joeyespo/inbox-by-gmail-checker/pull/18) - thanks, [@davo11122][]!) 43 | - Enhancement: Open Inbox in the current tab if it's the empty tab ([#20](https://github.com/joeyespo/inbox-by-gmail-checker/pull/20) - thanks, [@orschiro][]!) 44 | - Link to GitHub from the options page for questions and feedback 45 | 46 | 47 | #### Version 3.6.0 (2016-02-20) 48 | 49 | - Enhancement: Add Quiet Hours example 50 | - Bugfix: Actually fix the blurry icon on retina displays ([#14](https://github.com/joeyespo/inbox-by-gmail-checker/issues/14)) 51 | 52 | 53 | #### Version 3.5.0 (2016-02-19) 54 | 55 | - Enhancement: Fix the blurry icon on retina displays ([#14](https://github.com/joeyespo/inbox-by-gmail-checker/issues/14)) 56 | - Bugfix: Fix the connectivity problems ([#12](https://github.com/joeyespo/inbox-by-gmail-checker/issues/12)) 57 | 58 | 59 | #### Version 3.4.0 (2016-02-06) 60 | 61 | - Enhancement: Stop showing the distracting loading animation ([#11](https://github.com/joeyespo/inbox-by-gmail-checker/issues/11)) 62 | 63 | 64 | #### Version 3.3.0 (2016-02-05) 65 | 66 | - Enhancement: Add optional quite hours snooze color ([#9](https://github.com/joeyespo/inbox-by-gmail-checker/issues/9)) 67 | - Bugfix: Limit the poll input box ([#7](https://github.com/joeyespo/inbox-by-gmail-checker/issues/7)) 68 | - Bugfix: Limit the user ID's min value ([#10](https://github.com/joeyespo/inbox-by-gmail-checker/pull/10) - thanks, [@dpeukert][]!) 69 | 70 | 71 | #### Version 3.2.0 (2015-12-18) 72 | 73 | - Enhancement: Add polling option ([#5](https://github.com/joeyespo/grip/pull/5) - thanks, [@michliga][]!) 74 | - Enhancement: Allow checking inbox more frequently than once per minute ([#6](https://github.com/joeyespo/grip/pull/6)) 75 | - Enhancement: Show normalized values when you save the options 76 | - Add `CHANGES.md` and [`AUTHORS.md`](AUTHORS.md) 77 | 78 | 79 | #### Version 3.1.0 (2015-12-11) 80 | 81 | - Enhancement: Focus on the Inbox tab from *any* open window ([#4](https://github.com/joeyespo/grip/pull/4) - thanks, [@james0x0A][]!) 82 | 83 | 84 | ### Version 3.0.0 (2015-05-11) 85 | 86 | - Enhancement: Add quiet hours option 87 | - Code cleanup 88 | 89 | 90 | ### Version 2.0.0 (2014-12-16) 91 | 92 | - Enhancement: Add options page 93 | - Readme: Link to the Chrome Store 94 | 95 | 96 | ### Version 1.0.0 (2014-11-13) 97 | 98 | - First public preview release 99 | 100 | 101 | [@james0x0A]: https://github.com/james0x0A 102 | [@michliga]: https://github.com/michliga 103 | [@dpeukert]: https://github.com/dpeukert 104 | [@davo11122]: https://github.com/davo11122 105 | [@orschiro]: https://github.com/orschiro 106 | [@shali3]: https://github.com/shali3 107 | [@Najki]: https://github.com/Najki 108 | [@CarlosHBC]: https://github.com/CarlosHBC 109 | -------------------------------------------------------------------------------- /options.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Inbox by Gmail Options 5 | 6 | 7 | 8 |
9 |
10 |

Inbox by Gmail Options

11 |
12 |
/u/
13 |
Check a different account when you're signed into multiple.
14 |
15 |
16 |
sec
17 |
Frequency, in seconds, that your inbox is checked.
18 |
19 |
20 |
21 |
Comma-separated list of hours to disable notifications and hide the unread count each day. Example: Common working hours
22 |
23 |
24 |
25 |
Number of minutes to be quiet when "Go distraction-free" is selected. (Right-click the extension's icon to find this)
26 |
27 |
28 |
29 |
When checked, use for quiet and distraction-free time instead of
30 |
31 |
32 |
33 |
When checked, notifications will pop up when new email arrives.
34 |
35 |
36 |
37 |
When checked, adds "Share page via email" to your right-click menu.
38 |
39 |
40 |
41 |
When checked, focuses an existing Inbox tab instead of creating one.
42 |
43 |
44 |
45 |
When checked, navigates to your inbox using the current tab instead of a new one if the current tab is the "empty" tab.
46 |
47 |
48 | 49 | 50 |
51 |
52 |
53 |
54 |
55 |

Thanks for using Inbox by Gmail Checker!

56 |

If you enjoy this extension, please consider rating it in the Chrome Store.

57 |

Questions? Feedback? Open an issue on GitHub.

58 |

Version . See what's new.

59 |
60 | 64 | Fork me on GitHub 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /options.js: -------------------------------------------------------------------------------- 1 | function restoreOptions() { 2 | chrome.storage.sync.get({ 3 | defaultUser: '0', 4 | pollInterval: '3', 5 | quietHours: '', 6 | distractionFreeMinutes: '30', 7 | useSnoozeColor: true, 8 | useDesktopNotifications: true, 9 | showPageMenu: true, 10 | focusExistingInboxTab: false, 11 | openInEmptyTab: false 12 | }, function (items) { 13 | document.getElementById('defaultUser').value = items.defaultUser; 14 | document.getElementById('pollInterval').value = items.pollInterval || 3; 15 | document.getElementById('quietHours').value = items.quietHours; 16 | document.getElementById('distractionFreeMinutes').value = items.distractionFreeMinutes || 30; 17 | document.getElementById('useSnoozeColor').checked = !!items.useSnoozeColor; 18 | document.getElementById('showPageMenu').checked = !!items.showPageMenu; 19 | document.getElementById('useDesktopNotifications').checked = !!items.useDesktopNotifications; 20 | document.getElementById('openInEmptyTab').checked = !!items.openInEmptyTab; 21 | chrome.permissions.contains({ permissions: ['tabs'] }, function (result) { 22 | document.getElementById('focusExistingInboxTabError').textContent = items.focusExistingInboxTab && !result ? 23 | 'Error: "tabs" permission not granted. Re-check this option to try again.' : 24 | ''; 25 | document.getElementById('focusExistingInboxTab').checked = !!items.focusExistingInboxTab; 26 | }); 27 | }); 28 | } 29 | 30 | function saveOptions(e) { 31 | e.preventDefault(); 32 | 33 | // Normalize 34 | var defaultUser = Math.max(0, parseInt(document.getElementById('defaultUser').value) || 0); 35 | var pollInterval = Math.max(0, Math.min(3600, parseInt(document.getElementById('pollInterval').value) || 3)); 36 | var quietHours = document.getElementById('quietHours').value; 37 | var distractionFreeMinutes = Math.max(1, Math.min(1440, parseInt(document.getElementById('distractionFreeMinutes').value) || 30)); 38 | var useSnoozeColor = document.getElementById('useSnoozeColor').checked; 39 | var useDesktopNotifications = document.getElementById('useDesktopNotifications').checked; 40 | var showPageMenu = document.getElementById('showPageMenu').checked; 41 | var focusExistingInboxTab = document.getElementById('focusExistingInboxTab').checked; 42 | var openInEmptyTab = document.getElementById('openInEmptyTab').checked; 43 | chrome.storage.sync.set({ 44 | defaultUser: defaultUser, 45 | pollInterval: pollInterval, 46 | quietHours: quietHours, 47 | distractionFreeMinutes: distractionFreeMinutes, 48 | useSnoozeColor: useSnoozeColor, 49 | useDesktopNotifications: useDesktopNotifications, 50 | showPageMenu: showPageMenu, 51 | focusExistingInboxTab: focusExistingInboxTab, 52 | openInEmptyTab: openInEmptyTab 53 | }, function () { 54 | // Update status to let user know options were saved. 55 | var status = document.getElementById('status'); 56 | status.textContent = 'Options saved.'; 57 | setTimeout(function () { 58 | status.textContent = ''; 59 | }, 3000); 60 | }); 61 | 62 | // Show normalized values 63 | restoreOptions(); 64 | 65 | // Remove unused permissions 66 | if (!focusExistingInboxTab) { 67 | chrome.permissions.remove({ permissions: ['tabs'] }); 68 | } 69 | 70 | return false; 71 | } 72 | 73 | function defaultOptions() { 74 | document.getElementById('defaultUser').value = 0; 75 | document.getElementById('pollInterval').value = 3; 76 | document.getElementById('quietHours').value = ''; 77 | document.getElementById('distractionFreeMinutes').value = 30; 78 | document.getElementById('useSnoozeColor').checked = true; 79 | document.getElementById('useDesktopNotifications').checked = true; 80 | document.getElementById('showPageMenu').checked = true; 81 | document.getElementById('focusExistingInboxTab').checked = false; 82 | document.getElementById('openInEmptyTab').checked = false; 83 | } 84 | 85 | function main() { 86 | document.getElementById('version').innerHTML = chrome.runtime.getManifest().version; 87 | 88 | // Ensure permissions 89 | if (!chrome || !chrome.storage || !chrome.storage.sync) { 90 | var status = document.getElementById('status'); 91 | status.style.cssText = 'color:red;'; 92 | status.textContent = 'Error: Could not load settings. Please upgrade Chrome.'; 93 | return; 94 | } 95 | 96 | document.addEventListener('DOMContentLoaded', restoreOptions); 97 | document.getElementById('defaults').addEventListener('click', defaultOptions); 98 | document.getElementById('optionsForm').addEventListener('submit', saveOptions); 99 | document.getElementById('exampleQuietHours').addEventListener('click', function (e) { 100 | e.preventDefault(); 101 | document.getElementById('quietHours').value = '9,10,11,12,13,14,15,16,17,18'; 102 | return false; 103 | }); 104 | document.getElementById('focusExistingInboxTab').addEventListener('click', function (e) { 105 | if (document.getElementById('focusExistingInboxTab').checked) { 106 | chrome.permissions.contains({ permissions: ['tabs'] }, function (result) { 107 | if (!result) { 108 | alert('This option requires the following permission in order to locate Inbox tabs:\n\n \u2022 "tabs"\n\nIf prompted, select "Allow" to enable this feature.'); 109 | chrome.permissions.request({ permissions: ['tabs'] }, function (granted) { 110 | if (!granted) { 111 | document.getElementById('focusExistingInboxTab').checked = false; 112 | } 113 | }); 114 | } 115 | }); 116 | } 117 | return false; 118 | }); 119 | } 120 | 121 | main(); 122 | -------------------------------------------------------------------------------- /background.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | // Derivative work by Joe Esposito 5 | 6 | // Configuration 7 | var animationFrames = 36; 8 | var animationSpeed = 10; // ms 9 | var canvas = document.getElementById('canvas'); 10 | var loggedInImage = document.getElementById('logged_in'); 11 | var canvasContext = canvas.getContext('2d'); 12 | var pollIntervalDefault = 3; // 3 seconds 13 | var pollIntervalMax = 3600; // 1 hour 14 | var requestTimeout = 1000 * 2; // 2 seconds 15 | var tryAgainTime = 1000 * 5; // 5 seconds 16 | var rotation = 0; 17 | var loadingAnimation = new LoadingAnimation(); 18 | var openedLoginPage = false; 19 | var distractionFreeMode = false; 20 | var distractionFreeModeTimerId = null; 21 | 22 | var options = { 23 | defaultUser: 0, 24 | pollInterval: 0, 25 | quietHours: [], 26 | distractionFreeMinutes: 30, 27 | useSnoozeColor: true, 28 | useDesktopNotifications: true, 29 | showPageMenu: true, 30 | focusExistingInboxTab: false, 31 | openInEmptyTab: false 32 | }; 33 | 34 | // Legacy support for pre-event-pages 35 | var oldChromeVersion = !chrome.runtime; 36 | var requestTimerId; 37 | 38 | function isQuietTime() { 39 | if (distractionFreeMode) { 40 | return true; 41 | } 42 | var time = new Date(); 43 | return options.quietHours && options.quietHours.indexOf(time.getHours()) !== -1; 44 | } 45 | 46 | function getUser() { 47 | // Appends the /u/ route when default user is set and not equal to 0 48 | return options.defaultUser ? ('u/' + options.defaultUser + '/') : ''; 49 | } 50 | 51 | function getGmailBaseUrl() { 52 | return 'https://mail.google.com/'; 53 | } 54 | 55 | function getGmailUrl() { 56 | return getGmailBaseUrl() + 'mail/' + getUser(); 57 | } 58 | 59 | function getInboxBaseUrl() { 60 | return 'https://inbox.google.com/'; 61 | } 62 | 63 | function getInboxUrl() { 64 | return getInboxBaseUrl() + getUser(); 65 | } 66 | 67 | // Identifier used to debug the possibility of multiple instances of the 68 | // extension making requests on behalf of a single user. 69 | function getInstanceId() { 70 | if (!localStorage.hasOwnProperty('instanceId')) 71 | localStorage.instanceId = 'gmc' + parseInt(Date.now() * Math.random(), 10); 72 | return localStorage.instanceId; 73 | } 74 | 75 | function getFeedUrl() { 76 | // "zx" is a Gmail query parameter that is expected to contain a random 77 | // string and may be ignored/stripped. 78 | return getGmailUrl() + 'feed/atom?zx=' + encodeURIComponent(getInstanceId()); 79 | } 80 | 81 | function isInboxUrl(url) { 82 | // Return whether the URL starts with the Inbox prefix. 83 | return url.indexOf(getInboxBaseUrl()) === 0 || 84 | url.indexOf(getGmailBaseUrl()) === 0; 85 | } 86 | 87 | // A "loading" animation displayed while we wait for the first response from 88 | // Gmail. This animates the badge text with a dot that cycles from left to 89 | // right. 90 | function LoadingAnimation() { 91 | this.timerId_ = 0; 92 | this.maxCount_ = 8; // Total number of states in animation 93 | this.current_ = 0; // Current state 94 | this.maxDot_ = 4; // Max number of dots in animation 95 | } 96 | 97 | LoadingAnimation.prototype.paintFrame = function () { 98 | var text = ''; 99 | for (var i = 0; i < this.maxDot_; i++) { 100 | text += (i == this.current_) ? '.' : ' '; 101 | } 102 | if (this.current_ >= this.maxDot_) 103 | text += ''; 104 | 105 | chrome.browserAction.setBadgeBackgroundColor({ color: [0, 56, 206, 255] }); 106 | chrome.browserAction.setBadgeText({ text: text }); 107 | this.current_++; 108 | if (this.current_ == this.maxCount_) 109 | this.current_ = 0; 110 | } 111 | 112 | LoadingAnimation.prototype.start = function () { 113 | if (this.timerId_) 114 | return; 115 | 116 | var self = this; 117 | this.timerId_ = window.setInterval(function () { 118 | self.paintFrame(); 119 | }, 100); 120 | } 121 | 122 | LoadingAnimation.prototype.stop = function () { 123 | if (!this.timerId_) 124 | return; 125 | 126 | window.clearInterval(this.timerId_); 127 | this.timerId_ = 0; 128 | } 129 | 130 | function updateIcon() { 131 | if (!localStorage.hasOwnProperty('unreadCount')) { 132 | chrome.browserAction.setIcon({ 133 | path: { 134 | '19': 'media/inbox_not_logged_in.png', 135 | '38': 'media/inbox_not_logged_in_retina.png' 136 | } 137 | }); 138 | chrome.browserAction.setBadgeBackgroundColor({ color: [190, 190, 190, 230] }); 139 | chrome.browserAction.setBadgeText({ text: '?' }); 140 | } else { 141 | var quiet = isQuietTime(); 142 | var unreadCount = localStorage.unreadCount != '0' ? localStorage.unreadCount : ''; 143 | chrome.browserAction.setIcon({ 144 | path: { 145 | '19': quiet && options.useSnoozeColor ? 'media/inbox_quiet.png' : 'media/inbox_logged_in.png', 146 | '38': quiet && options.useSnoozeColor ? 'media/inbox_quiet_retina.png' : 'media/inbox_logged_in_retina.png' 147 | } 148 | }); 149 | chrome.browserAction.setBadgeBackgroundColor({ color: [0, 56, 206, 255] }); 150 | chrome.browserAction.setBadgeText({ 151 | text: (quiet ? '' : unreadCount) 152 | }); 153 | } 154 | } 155 | 156 | function scheduleRequest() { 157 | console.log('scheduleRequest'); 158 | var pollInterval = options.pollInterval || pollIntervalDefault; 159 | var multiplier = Math.pow(2, localStorage.requestFailureCount || 0); 160 | // Use different logic for smaller poll intervals 161 | if (pollInterval < 1) { 162 | pollInterval *= multiplier; 163 | } else { 164 | var randomness = Math.random() * 2; 165 | var fuzzyMultiplier = Math.max(randomness * multiplier, 1); 166 | pollInterval = Math.round(fuzzyMultiplier * pollInterval); 167 | } 168 | var delay = Math.min(pollInterval, pollIntervalMax); 169 | console.log('Scheduling for: ' + delay + ' seconds'); 170 | 171 | if (oldChromeVersion) { 172 | if (requestTimerId) { 173 | window.clearTimeout(requestTimerId); 174 | } 175 | requestTimerId = window.setTimeout(onAlarm, delay * 1000); 176 | } else { 177 | console.log('Creating alarm'); 178 | // Use a repeating alarm so that it fires again if there was a problem 179 | // setting the next alarm. 180 | chrome.alarms.create('refresh', {periodInMinutes: delay / 60.0}); 181 | } 182 | } 183 | 184 | // ajax stuff 185 | function startRequest(params) { 186 | // Schedule request immediately. We want to be sure to reschedule, even in the 187 | // case where the extension process shuts down while this request is 188 | // outstanding. 189 | if (params && params.scheduleRequest) scheduleRequest(); 190 | 191 | function stopLoadingAnimation() { 192 | if (params && params.showLoadingAnimation) loadingAnimation.stop(); 193 | } 194 | 195 | if (params && params.showLoadingAnimation) 196 | loadingAnimation.start(); 197 | 198 | getInboxCount( 199 | function (count) { 200 | stopLoadingAnimation(); 201 | updateUnreadCount(count); 202 | openedLoginPage = false; 203 | }, 204 | function () { 205 | stopLoadingAnimation(); 206 | delete localStorage.unreadCount; 207 | updateIcon(); 208 | } 209 | ); 210 | } 211 | 212 | function getInboxCount(onSuccess, onError) { 213 | var xhr = new XMLHttpRequest(); 214 | var abortTimerId = window.setTimeout(function () { 215 | if (xhr) { 216 | xhr.abort(); // synchronously calls onreadystatechange 217 | } 218 | cleanup(); 219 | }, requestTimeout); 220 | 221 | function cleanup() { 222 | window.clearTimeout(abortTimerId); 223 | xhr.onreadystatechange = null; 224 | xhr = null; 225 | } 226 | 227 | function handleSuccess(count) { 228 | cleanup(); 229 | localStorage.requestFailureCount = 0; 230 | if (onSuccess) { 231 | onSuccess(count); 232 | } 233 | } 234 | 235 | var invokedErrorCallback = false; 236 | function handleError() { 237 | console.error('handleError() called'); 238 | cleanup(); 239 | ++localStorage.requestFailureCount; 240 | if (onError && !invokedErrorCallback) { 241 | onError(); 242 | } 243 | invokedErrorCallback = true; 244 | } 245 | 246 | try { 247 | xhr.onreadystatechange = function () { 248 | if (this.readyState != 4) { 249 | return; 250 | } 251 | 252 | // Check for edge case where mail.google.com has not yet been visited and try again 253 | if (this.status === 401) { 254 | console.log('Got error 401 while getting inbox count'); 255 | if (openedLoginPage) { 256 | console.log('Login page already opened - waiting for user to authenticate'); 257 | } else { 258 | // Visit regular gmail to authorize feed access 259 | openedLoginPage = true; 260 | console.log('Opening', getGmailUrl()); 261 | chrome.tabs.create({ url: getGmailUrl() }); 262 | } 263 | } else if (this.responseXML) { 264 | var xmlDoc = this.responseXML; 265 | var fullCountSet = xmlDoc.evaluate('/gmail:feed/gmail:fullcount', xmlDoc, gmailNSResolver, XPathResult.ANY_TYPE, null); 266 | var fullCountNode = fullCountSet.iterateNext(); 267 | if (fullCountNode) { 268 | handleSuccess(fullCountNode.textContent); 269 | return; 270 | } else { 271 | console.error(chrome.i18n.getMessage('gmailcheck_node_error')); 272 | } 273 | } 274 | 275 | handleError(); 276 | }; 277 | 278 | xhr.onerror = function (error) { 279 | handleError(); 280 | }; 281 | 282 | xhr.open('GET', getFeedUrl(), true); 283 | xhr.send(null); 284 | } catch(e) { 285 | console.error(chrome.i18n.getMessage('gmailcheck_exception', e)); 286 | handleError(); 287 | } 288 | } 289 | 290 | function gmailNSResolver(prefix) { 291 | if(prefix == 'gmail') { 292 | return 'http://purl.org/atom/ns#'; 293 | } 294 | } 295 | 296 | function updateUnreadCount(count) { 297 | var quietTime = isQuietTime(); 298 | var changed = localStorage.unreadCount != count || String(localStorage.quietTime) != String(quietTime); 299 | if (changed) { 300 | notify(count); 301 | } 302 | localStorage.unreadCount = count; 303 | localStorage.quietTime = quietTime; 304 | updateIcon(); 305 | if (changed) { 306 | animateFlip(); 307 | } 308 | } 309 | 310 | 311 | function ease(x) { 312 | return (1-Math.sin(Math.PI/2+x*Math.PI))/2; 313 | } 314 | 315 | function animateFlip() { 316 | rotation += 1/animationFrames; 317 | drawIconAtRotation(); 318 | 319 | if (rotation <= 1) { 320 | setTimeout(animateFlip, animationSpeed); 321 | } else { 322 | rotation = 0; 323 | updateIcon(); 324 | } 325 | } 326 | 327 | function drawIconAtRotation() { 328 | canvasContext.save(); 329 | canvasContext.clearRect(0, 0, canvas.width, canvas.height); 330 | canvasContext.translate( 331 | Math.ceil(canvas.width/2), 332 | Math.ceil(canvas.height/2)); 333 | canvasContext.rotate(2*Math.PI*ease(rotation)); 334 | canvasContext.drawImage(loggedInImage, 335 | -Math.ceil(canvas.width/2), 336 | -Math.ceil(canvas.height/2)); 337 | canvasContext.restore(); 338 | 339 | chrome.browserAction.setIcon({ 340 | imageData: canvasContext.getImageData(0, 0, canvas.width,canvas.height) 341 | }); 342 | } 343 | 344 | function goToNewInbox() { 345 | // Navigate the empty tab if preferred, or create a new Inbox tab 346 | if (options.openInEmptyTab) { 347 | console.log('Navigating empty tab to Inbox...'); 348 | // Check if current tab is the empty tab 349 | chrome.tabs.query({ currentWindow: true, active: true }, function (tabs) { 350 | var tab = tabs[0] 351 | if (tab && tab.url === 'chrome://newtab/') { 352 | chrome.tabs.update({ url: getInboxUrl() }); 353 | } else { 354 | chrome.tabs.create({ url: getInboxUrl() }); 355 | } 356 | }); 357 | } else { 358 | console.log('Creating new Inbox tab...'); 359 | chrome.tabs.create({ url: getInboxUrl() }); 360 | } 361 | } 362 | 363 | function goToExistingInbox() { 364 | console.log('Going to inbox...'); 365 | chrome.tabs.query({ url: '*://inbox.google.com/*', currentWindow: true }, function (tabs) { 366 | var tab = tabs[0]; 367 | if (tab) { 368 | console.log('Found Inbox tab: ' + tab.url + '. Focusing and refreshing count...'); 369 | chrome.tabs.update(tab.id, { selected: true, highlighted: true }); 370 | startRequest({ scheduleRequest: false, showLoadingAnimation: false }); 371 | } else { 372 | console.log('Could not find Inbox tab. Creating one...'); 373 | goToNewInbox(); 374 | } 375 | }); 376 | } 377 | 378 | function goToInbox() { 379 | chrome.tabs.query({ url: '*://inbox.google.com/*', active: true, currentWindow: true }, function (tabs) { 380 | var tab = tabs[0]; 381 | // Do nothing if current tab is Inbox 382 | var inboxUrl = getInboxUrl(); 383 | if (tab && tab.url && tab.url.substr(0, inboxUrl.length) === inboxUrl) { 384 | return; 385 | } 386 | // Go to existing Inbox tab or create a new one 387 | if (options.focusExistingInboxTab) { 388 | goToExistingInbox(); 389 | } else { 390 | goToNewInbox(); 391 | } 392 | }); 393 | 394 | // Clear notifications 395 | if (chrome.notifications && chrome.notifications.clear) { 396 | chrome.notifications.clear('inboxUpdate'); 397 | } 398 | } 399 | 400 | function onInit() { 401 | console.log('onInit'); 402 | localStorage.requestFailureCount = 0; // used for exponential backoff 403 | startRequest({ scheduleRequest: true, showLoadingAnimation: true }); 404 | if (!oldChromeVersion) { 405 | // TODO(mpcomplete): We should be able to remove this now, but leaving it 406 | // for a little while just to be sure the refresh alarm is working nicely. 407 | chrome.alarms.create('watchdog', { periodInMinutes: 5 }); 408 | } 409 | } 410 | 411 | function onAlarm(alarm) { 412 | console.log('Got alarm', alarm); 413 | // |alarm| can be undefined because onAlarm also gets called from 414 | // window.setTimeout on old chrome versions. 415 | if (alarm && alarm.name == 'watchdog') { 416 | onWatchdog(); 417 | } else { 418 | startRequest({ scheduleRequest: true, showLoadingAnimation: false }); 419 | } 420 | } 421 | 422 | function onWatchdog() { 423 | chrome.alarms.get('refresh', function (alarm) { 424 | if (alarm) { 425 | console.log('Refresh alarm exists. Yay.'); 426 | } else { 427 | console.log('Refresh alarm doesn\'t exist!? ' + 428 | 'Refreshing now and rescheduling.'); 429 | startRequest({ scheduleRequest: true, showLoadingAnimation: false }); 430 | } 431 | }); 432 | } 433 | 434 | function onNavigate(details) { 435 | if (details.url && isInboxUrl(details.url)) { 436 | console.log('Recognized Inbox navigation to: ' + details.url + '. Refreshing count...'); 437 | startRequest({ scheduleRequest: false, showLoadingAnimation: false }); 438 | } 439 | } 440 | 441 | function onShareToInbox(info, tab) { 442 | chrome.tabs.create({ 443 | url: getInboxUrl() + '?&subject=' + encodeURIComponent(tab.title) + '&body=' + encodeURIComponent(tab.url) 444 | }); 445 | } 446 | 447 | function resetDistractionFreeMode() { 448 | // Turn off distraction-free mode, reflect this in the context menu, and clear any outstanding timers 449 | distractionFreeMode = false; 450 | chrome.contextMenus.update('distractionFreeInbox', { title: 'Go distraction-free for ' + options.distractionFreeMinutes + ' min' }); 451 | if (distractionFreeModeTimerId) { 452 | window.clearTimeout(distractionFreeModeTimerId); 453 | distractionFreeModeTimerId = null; 454 | } 455 | } 456 | 457 | function onDistractionFreeMode(info, tab) { 458 | // Update distraction-free mode and reflect this in the context menu 459 | if (!distractionFreeMode) { 460 | console.log('Ending distraction-free mode in ' + options.distractionFreeMinutes + ' minutes'); 461 | resetDistractionFreeMode(); 462 | distractionFreeMode = true; 463 | chrome.contextMenus.update('distractionFreeInbox', { title: 'Leave distraction-free mode' }); 464 | distractionFreeModeTimerId = window.setTimeout(resetDistractionFreeMode, options.distractionFreeMinutes * 60 * 1000); 465 | } else { 466 | console.log('Distraction-free mode ended'); 467 | resetDistractionFreeMode() 468 | } 469 | 470 | refresh(); 471 | } 472 | 473 | function onOptionsLoaded() { 474 | // Update distraction-free mode minutes 475 | if (!distractionFreeMode) { 476 | chrome.contextMenus.update('distractionFreeInbox', { title: 'Go distraction-free for ' + options.distractionFreeMinutes + ' min' }); 477 | } 478 | 479 | // Update context menu 480 | var contexts = ['browser_action'] 481 | if (options.showPageMenu) { 482 | contexts.push('page'); 483 | } 484 | chrome.contextMenus.update('shareToInbox', { contexts: contexts }); 485 | 486 | refresh(); 487 | } 488 | 489 | function loadHoursList(s) { 490 | if (!s) { 491 | return []; 492 | } 493 | 494 | var hourStrings = s.split(','); 495 | var hours = []; 496 | for (var i = 0; i < hourStrings.length; i++) { 497 | var hour = parseInt(hourStrings[i], 10); 498 | if (!isNaN(hour) && hour >= 0 && hour < 24) { 499 | hours.push(hour); 500 | } 501 | } 502 | return hours; 503 | } 504 | 505 | function loadOptions(callback) { 506 | // Do nothing if storage is not permitted 507 | if (!chrome || !chrome.storage || !chrome.storage.sync) { 508 | callback(false); 509 | return; 510 | } 511 | 512 | // Load options from storage (with fallbacks) 513 | chrome.storage.sync.get({ 514 | defaultUser: 0, 515 | pollInterval: 0, 516 | quietHours: '', 517 | distractionFreeMinutes: 30, 518 | useSnoozeColor: true, 519 | useDesktopNotifications: true, 520 | showPageMenu: true, 521 | focusExistingInboxTab: false, 522 | openInEmptyTab: false 523 | }, function (items) { 524 | options.defaultUser = items.defaultUser; 525 | options.pollInterval = parseInt(items.pollInterval, 10) || 0; 526 | options.quietHours = loadHoursList(items.quietHours); 527 | options.distractionFreeMinutes = parseInt(items.distractionFreeMinutes, 10) || 30; 528 | options.useSnoozeColor = !!items.useSnoozeColor; 529 | options.focusExistingInboxTab = !!items.focusExistingInboxTab; 530 | options.showPageMenu = !!items.showPageMenu; 531 | options.useDesktopNotifications = !!items.useDesktopNotifications; 532 | options.openInEmptyTab = !!items.openInEmptyTab; 533 | callback(true); 534 | }); 535 | } 536 | 537 | function refresh() { 538 | startRequest({ scheduleRequest: true, showLoadingAnimation: false }); 539 | } 540 | 541 | function notify(count) { 542 | var newMessagesCount = count - localStorage.unreadCount; 543 | 544 | if (options.useDesktopNotifications && !isQuietTime() && newMessagesCount > 0) { 545 | chrome.notifications.create('inboxUpdate', { 546 | type: 'basic', 547 | iconUrl: 'media/icon_256.png', 548 | title: 'Inbox by Gmail Checker', 549 | isClickable: true, 550 | contextMessage: 'Click to open Inbox', 551 | message: 'You have ' + (newMessagesCount === 1 ? 'a': newMessagesCount) +' new message' + (newMessagesCount === 1 ? '' : 's') + '.' 552 | }); 553 | } 554 | } 555 | 556 | function main() { 557 | if (oldChromeVersion) { 558 | updateIcon(); 559 | onInit(); 560 | } else { 561 | chrome.runtime.onInstalled.addListener(onInit); 562 | chrome.alarms.onAlarm.addListener(onAlarm); 563 | } 564 | 565 | // Update mail count when Inbox is visited without clicking the app icon 566 | if (chrome.webNavigation && chrome.webNavigation.onDOMContentLoaded && chrome.webNavigation.onReferenceFragmentUpdated) { 567 | // NOTE: Keep this "webNavigation" code in here in case the permission is ever added back in 568 | // e.g. "webNavigation" no longer shows a "Read your browsing history" permission warning, "tabs" is required 569 | // again by this project, or certain "webNavigation" actions become workable without the permission 570 | // TODO(aa): Cannot use urlPrefix because all the url fields lack the protocol part (see crbug.com/140238) 571 | var filters = { url: [{ urlContains: getInboxBaseUrl().replace(/^https?\:\/\//, '') }] }; 572 | chrome.webNavigation.onDOMContentLoaded.addListener(onNavigate, filters); 573 | chrome.webNavigation.onReferenceFragmentUpdated.addListener(onNavigate, filters); 574 | } else { 575 | chrome.tabs.onUpdated.addListener(function (_, details) { 576 | onNavigate(details); 577 | }); 578 | } 579 | 580 | // Handle main click action 581 | chrome.browserAction.onClicked.addListener(goToInbox); 582 | 583 | // Handle notification clicks, if notifications are supported 584 | if (chrome.notifications && chrome.notifications.onClicked) { 585 | chrome.notifications.onClicked.addListener(goToInbox); 586 | } 587 | 588 | // Create context menu items 589 | if (chrome.contextMenus && chrome.contextMenus.create && chrome.contextMenus.onClicked) { 590 | chrome.contextMenus.create({ id: 'distractionFreeInbox', title: 'Go distraction-free', contexts: ['browser_action'] }); 591 | chrome.contextMenus.create({ id: 'shareToInbox', title: 'Share page via email', contexts: ['browser_action', 'page'] }); 592 | chrome.contextMenus.onClicked.addListener(function (info, tab) { 593 | if (info.menuItemId === 'shareToInbox') { 594 | onShareToInbox(info, tab); 595 | } else if (info.menuItemId === 'distractionFreeInbox') { 596 | onDistractionFreeMode(info, tab); 597 | } 598 | }); 599 | } 600 | 601 | if (chrome.runtime && chrome.runtime.onStartup) { 602 | chrome.runtime.onStartup.addListener(function () { 603 | console.log('Starting browser... updating icon.'); 604 | startRequest({ scheduleRequest: false, showLoadingAnimation: false }); 605 | updateIcon(); 606 | }); 607 | } else { 608 | // This hack is needed because Chrome 22 does not persist browserAction icon 609 | // state, and also doesn't expose onStartup. So the icon always starts out in 610 | // wrong state. We don't actually use onStartup except as a clue that we're 611 | // in a version of Chrome that has this problem. 612 | chrome.windows.onCreated.addListener(function () { 613 | console.log('Window created... updating icon.'); 614 | startRequest({ scheduleRequest: false, showLoadingAnimation: false }); 615 | updateIcon(); 616 | }); 617 | } 618 | 619 | // Load options and re-load them when they're changed 620 | loadOptions(function () { 621 | onOptionsLoaded(); 622 | chrome.storage.onChanged.addListener(function (changes, namespace) { 623 | loadOptions(function () { 624 | onOptionsLoaded(); 625 | }); 626 | }); 627 | }); 628 | } 629 | 630 | main(); 631 | --------------------------------------------------------------------------------