├── .github └── FUNDING.yml ├── .gitignore ├── .vscode ├── launch.json └── settings.json ├── AUTHORS ├── LICENSE ├── README.md ├── data ├── application.css ├── coffee-resource.xml ├── com.github.nick92.coffee.appdata.xml ├── com.github.nick92.coffee.desktop ├── com.github.nick92.coffee.gschema.xml ├── icons │ ├── 128x128 │ │ ├── coffee-news.svg │ │ └── com.github.nick92.coffee.svg │ ├── 16x16 │ │ ├── coffee-news.svg │ │ └── com.github.nick92.coffee.svg │ ├── 32x32 │ │ ├── coffee-news.svg │ │ ├── coffee.svg │ │ ├── com.github.nick92.coffee.svg │ │ └── news.png │ ├── 48x48 │ │ ├── coffee-news.svg │ │ ├── com.github.nick92.coffee.svg │ │ ├── news.png │ │ ├── owl-new.svg │ │ └── owl.svg │ ├── 512x512 │ │ ├── coffee-news.svg │ │ ├── com.github.nick92.coffee.svg │ │ └── news.png │ ├── 64x64 │ │ ├── coffee-news.svg │ │ └── com.github.nick92.coffee.svg │ ├── coffee-news.png │ ├── coffee-news.svg │ ├── meson.build │ ├── news │ │ └── question.png │ └── symbol │ │ ├── coffee-news-symbolic.svg │ │ ├── list-add-symbolic.svg │ │ ├── preferences-system-symbolic.svg │ │ ├── selection-check.svg │ │ ├── view-refresh-symbolic.svg │ │ └── window-close-symbolic.svg ├── install_schema.py └── meson.build ├── debian ├── changelog ├── compat ├── control ├── copyright ├── rules └── source │ └── format ├── deps.sh ├── docs ├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── css │ ├── new-age.css │ └── new-age.min.css ├── gulpfile.js ├── img │ ├── coffee.ico │ ├── coffee.svg │ ├── distributor-logo-ubuntu.svg │ └── settings.png ├── index.html ├── js │ ├── new-age.js │ └── new-age.min.js ├── package.json ├── scss │ ├── _bootstrap-overrides.scss │ ├── _contact.scss │ ├── _cta.scss │ ├── _download.scss │ ├── _features.scss │ ├── _footer.scss │ ├── _global.scss │ ├── _masthead.scss │ ├── _mixins.scss │ ├── _navbar.scss │ ├── _variables.scss │ └── new-age.scss └── vendor │ ├── bootstrap │ ├── css │ │ ├── bootstrap-grid.css │ │ ├── bootstrap-grid.min.css │ │ ├── bootstrap-reboot.css │ │ ├── bootstrap-reboot.min.css │ │ ├── bootstrap.css │ │ └── bootstrap.min.css │ └── js │ │ ├── bootstrap.js │ │ └── bootstrap.min.js │ ├── font-awesome │ ├── css │ │ ├── font-awesome.css │ │ └── font-awesome.min.css │ ├── fonts │ │ ├── FontAwesome.otf │ │ ├── fontawesome-webfont.eot │ │ ├── fontawesome-webfont.svg │ │ ├── fontawesome-webfont.ttf │ │ ├── fontawesome-webfont.woff │ │ └── fontawesome-webfont.woff2 │ ├── less │ │ ├── animated.less │ │ ├── bordered-pulled.less │ │ ├── core.less │ │ ├── fixed-width.less │ │ ├── font-awesome.less │ │ ├── icons.less │ │ ├── larger.less │ │ ├── list.less │ │ ├── mixins.less │ │ ├── path.less │ │ ├── rotated-flipped.less │ │ ├── screen-reader.less │ │ ├── stacked.less │ │ └── variables.less │ └── scss │ │ ├── _animated.scss │ │ ├── _bordered-pulled.scss │ │ ├── _core.scss │ │ ├── _fixed-width.scss │ │ ├── _icons.scss │ │ ├── _larger.scss │ │ ├── _list.scss │ │ ├── _mixins.scss │ │ ├── _path.scss │ │ ├── _rotated-flipped.scss │ │ ├── _screen-reader.scss │ │ ├── _stacked.scss │ │ ├── _variables.scss │ │ └── font-awesome.scss │ ├── jquery-easing │ ├── jquery.easing.compatibility.js │ ├── jquery.easing.js │ └── jquery.easing.min.js │ ├── jquery │ ├── jquery.js │ └── jquery.min.js │ ├── popper │ ├── popper.js │ └── popper.min.js │ └── simple-line-icons │ ├── css │ └── simple-line-icons.css │ ├── fonts │ ├── Simple-Line-Icons.eot │ ├── Simple-Line-Icons.svg │ ├── Simple-Line-Icons.ttf │ ├── Simple-Line-Icons.woff │ └── Simple-Line-Icons.woff2 │ ├── less │ └── simple-line-icons.less │ └── scss │ └── simple-line-icons.scss ├── meson.build ├── meson └── post_install.py ├── snap ├── .snapcraft │ └── state └── snapcraft.yaml ├── src ├── CoffeeBar.vala ├── Logger.vala ├── Main.vala ├── Post.vala ├── Settings │ ├── General │ │ ├── AboutGrid.vala │ │ └── StripeDialog.vala │ ├── News │ │ ├── Dialog │ │ │ ├── NewsListRow.vala │ │ │ ├── NewsSourcesGet.vala │ │ │ ├── NewsSourcesList.vala │ │ │ └── Sidebar.vala │ │ ├── NewsContainer.vala │ │ ├── NewsGrid.vala │ │ └── NewsSource.vala │ ├── Settings.vala │ ├── SettingsWindow.vala │ └── Weather │ │ └── LocationGrid.vala ├── Views │ ├── NewsView.vala │ └── WeatherView.vala ├── Weather.vala ├── Widgets │ ├── MessageDialog.vala │ ├── NewsFlowBox.vala │ ├── NewsItem.vala │ ├── Selector.vala │ ├── WeatherFlowBox.vala │ ├── WeatherHeaderFlow.vala │ ├── WeatherHeaderItem.vala │ └── WeatherItem.vala ├── Worker │ ├── Parser.vala │ ├── Retriever.vala │ └── Sources.vala ├── config.vala.in └── meson.build └── vapi ├── keybinder-3.0.vapi └── libgeoclue-2.0.vapi /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: nickwilkins 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with a single custom sponsorship URL 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "lldb", 9 | "request": "launch", 10 | "name": "Debug", 11 | "program": "${workspaceFolder}/build/src/com.github.nick92.coffee", 12 | "args": [], 13 | "cwd": "${workspaceFolder}" 14 | } 15 | ] 16 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "mesonbuild.configureOnOpen": true 3 | } -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Nick Wilkins -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Coffee 2 | 3 | Keep up-to-date with current news and weather with Coffee. 4 | 5 | ## Download 6 | 7 | Download and install from the Coffee site 8 | 9 | [Download](https://nick92.github.io/coffee/#download) 10 | 11 | ## Building and Installing from code 12 | 13 | You'll need the following dependencies: 14 | 15 | libglib2.0-dev 16 | libgtk-3-dev 17 | libjson-glib-dev 18 | libsoup2.4-dev 19 | libgee-0.8-dev 20 | libgeocode-glib-dev 21 | libgeoclue-2-dev 22 | meson 23 | valac 24 | 25 | ### Build with Meson 26 | 27 | mkdir build 28 | meson build --prefix=/usr 29 | ninja 30 | 31 | ### Install & Run 32 | 33 | sudo ninja install 34 | ./src/com.github.nick92.coffee 35 | -------------------------------------------------------------------------------- /data/application.css: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2017 elementary LLC. (https://elementary.io) 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | .titlebar { 19 | padding-top: 0; 20 | padding-bottom: 0; 21 | } 22 | 23 | .addbutton { 24 | background-color: alpha (#4CAF50, 0.6); 25 | background-image: none; 26 | border-color: alpha (#4CAF50, 0.7); 27 | box-shadow: none; 28 | font-weight: 200; 29 | font-size: 15px; 30 | color: #fff; 31 | } 32 | 33 | .banner progressbar { 34 | color: @banner_fg_color; 35 | } 36 | 37 | .h1 { 38 | font-size: 20px; 39 | font-weight: 400; 40 | /*padding-bottom: 10px; 41 | border-bottom: 1px solid #4d4d4d; 42 | border-bottom: medium solid #4d4d4d; */ 43 | } 44 | 45 | .h2 { 46 | font-size: 18px; 47 | font-weight: 300; 48 | } 49 | 50 | .h3 { 51 | font-size: 15px; 52 | font-weight: 200; 53 | } 54 | 55 | .h4 { 56 | font-size: 6px; 57 | } 58 | 59 | flowboxchild, 60 | GtkFlowBox .grid-child { 61 | background-color: #f4f5f7; 62 | border: 1px solid alpha (#000, 0.15); 63 | border-radius: 5px; 64 | color: #4d4d4d; 65 | box-shadow: inset 0 0 0 1px alpha (#fff, 0.05), 66 | inset 0 1px 0 0 alpha (#fff, 0.45), 67 | inset 0 -1px 0 0 alpha (#fff, 0.15), 68 | 0 3px 2px -1px alpha (#000, 0.15), 69 | 0 3px 5px alpha (#000, 0.10); 70 | } 71 | 72 | flowboxchild:focus .card, 73 | GtkFlowBox .grid-child:focus .card { 74 | border: 1px solid alpha (#000, 0.2); 75 | border-radius: 3px; 76 | color: #4d4d4d; 77 | } 78 | -------------------------------------------------------------------------------- /data/coffee-resource.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | application.css 5 | icons/symbol/coffee-news-symbolic.svg 6 | icons/symbol/selection-check.svg 7 | icons/symbol/preferences-system-symbolic.svg 8 | icons/symbol/view-refresh-symbolic.svg 9 | icons/symbol/window-close-symbolic.svg 10 | icons/symbol/list-add-symbolic.svg 11 | icons/news/question.png 12 | 13 | -------------------------------------------------------------------------------- /data/com.github.nick92.coffee.appdata.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | com.github.nick92.coffee.desktop 5 | CC0 6 | Coffee 7 | Get the latest weather and news 8 | Nick Wilkins 9 | https://nick92.github.io/coffee/ 10 | https://github.com/nick92/coffee/issues/ 11 | 12 | 13 | https://i.imgur.com/t44PLJr.png 14 | 15 | 16 | 17 |

18 | Catch up with the latest news and weather with Coffee 19 |

20 |
    21 |
  • Choose from various news sources around the web
  • 22 |
  • Displays current and 5 day weather forecast for your location
  • 23 |
24 |

25 | Coffee provides current weather information for your location and news reports from various sources, take 26 | a break from hard work and catch up with the lastest news from around the internet 27 |

28 |
29 | 30 | #7b4397 31 | #ffffff 32 | 1 33 | 34 |
35 | -------------------------------------------------------------------------------- /data/com.github.nick92.coffee.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Name=Coffee 3 | Exec=com.github.nick92.coffee 4 | Icon=com.github.nick92.coffee 5 | Terminal=false 6 | Type=Application 7 | StartupNotify=true 8 | Categories=Network;Feed;News;GNOME;GTK; 9 | Keywords=News;Feed; 10 | -------------------------------------------------------------------------------- /data/com.github.nick92.coffee.gschema.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | true 5 | First load of Coffee 6 | 7 | 8 | 9 | true 10 | Enable weather widget 11 | 12 | 13 | 14 | true 15 | Enable news widget 16 | 17 | 18 | 19 | true 20 | Use dark sky feed for weather 21 | 22 | 23 | 24 | false 25 | Use Open Weather Map feed for weather 26 | 27 | 28 | 29 | "" 30 | Geolocation from weather report 31 | 32 | 33 | 34 | "" 35 | Location name from weather report 36 | 37 | 38 | 39 | "" 40 | News sources in news list but not used in application 41 | 42 | 43 | 44 | "" 45 | News sources currently being used 46 | 47 | 48 | 49 | true 50 | Get geolocation automatically 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /data/icons/16x16/coffee-news.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 14 | 15 | 16 | 17 | 18 | 19 | 21 | 22 | 24 | 27 | 28 | 30 | 31 | 43 | 46 | 49 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /data/icons/16x16/com.github.nick92.coffee.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 14 | 15 | 16 | 17 | 18 | 19 | 21 | 22 | 24 | 27 | 28 | 30 | 31 | 43 | 46 | 49 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /data/icons/32x32/coffee.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 12 | 13 | 14 | 15 | 16 | 17 | 19 | 21 | 22 | 23 | 25 | 26 | 27 | 39 | 42 | 45 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /data/icons/32x32/news.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick92/coffee/2bae1178be34bbf72a92143a4534ac2e739b4a8d/data/icons/32x32/news.png -------------------------------------------------------------------------------- /data/icons/48x48/news.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick92/coffee/2bae1178be34bbf72a92143a4534ac2e739b4a8d/data/icons/48x48/news.png -------------------------------------------------------------------------------- /data/icons/48x48/owl.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 15 | 16 | 17 | 18 | 20 | 21 | 22 | 23 | 26 | 28 | 29 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /data/icons/512x512/news.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick92/coffee/2bae1178be34bbf72a92143a4534ac2e739b4a8d/data/icons/512x512/news.png -------------------------------------------------------------------------------- /data/icons/coffee-news.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick92/coffee/2bae1178be34bbf72a92143a4534ac2e739b4a8d/data/icons/coffee-news.png -------------------------------------------------------------------------------- /data/icons/meson.build: -------------------------------------------------------------------------------- 1 | sizes = ['16x16', '32x32', '48x48' , '64x64', '128x128', '512x512'] 2 | themedir = get_option('datadir') + '/icons/hicolor/' 3 | 4 | foreach size: sizes 5 | install_data(size + '/com.github.nick92.coffee.svg', install_dir: themedir + size + '/apps/') 6 | endforeach 7 | -------------------------------------------------------------------------------- /data/icons/news/question.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick92/coffee/2bae1178be34bbf72a92143a4534ac2e739b4a8d/data/icons/news/question.png -------------------------------------------------------------------------------- /data/icons/symbol/coffee-news-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 10 | 11 | 12 | 13 | 14 | 15 | Gnome Symbolic Icon Theme 16 | 18 | 19 | 21 | 23 | 24 | 25 | 36 | 39 | 42 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /data/icons/symbol/list-add-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /data/icons/symbol/preferences-system-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | image/svg+xml 12 | 13 | Paper Symbolic Icon Theme 14 | 15 | 16 | 17 | Paper Symbolic Icon Theme 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /data/icons/symbol/selection-check.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 14 | 16 | 18 | 20 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 30 | 31 | -------------------------------------------------------------------------------- /data/icons/symbol/view-refresh-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | image/svg+xml 12 | 13 | Paper Symbolic Icon Theme 14 | 15 | 16 | 17 | Paper Symbolic Icon Theme 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /data/icons/symbol/window-close-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | image/svg+xml 12 | 13 | Paper Symbolic Icon Theme 14 | 15 | 16 | 17 | Paper Symbolic Icon Theme 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /data/install_schema.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import os 4 | import subprocess 5 | 6 | schemadir = os.path.join(os.environ['MESON_INSTALL_PREFIX'], 'share', 'glib-2.0', 'schemas') 7 | 8 | if not os.environ.get('DESTDIR'): 9 | print('Compiling gsettings schemas...') 10 | subprocess.call(['glib-compile-schemas', schemadir]) -------------------------------------------------------------------------------- /data/meson.build: -------------------------------------------------------------------------------- 1 | gnome = import ('gnome') 2 | 3 | coffee_resources = gnome.compile_resources ('coffee_resources', 'coffee-resource.xml', source_dir: '.', c_name: 'coffee') 4 | 5 | install_data('com.github.nick92.coffee.desktop', 6 | install_dir : join_paths('share', 'applications')) 7 | 8 | install_data('com.github.nick92.coffee.gschema.xml', 9 | install_dir : join_paths('share', 'glib-2.0', 'schemas')) 10 | 11 | install_data('com.github.nick92.coffee.appdata.xml', 12 | install_dir : join_paths('share', 'metainfo')) 13 | 14 | subdir('icons') 15 | 16 | meson.add_install_script('install_schema.py') -------------------------------------------------------------------------------- /debian/changelog: -------------------------------------------------------------------------------- 1 | com.github.nick92.coffee (1.1.0~ubuntu16.10) xenial; urgency=medium 2 | 3 | * 35 news sources added to list 4 | * New window to browse sources via categories 5 | * fix for weather forecast icons height 6 | * Geolocation fix to get different name if one value is null 7 | * Fix news reload issue when pressing F5 with automatic Geolocation turned on 8 | 9 | -- Nick Wilkins Wed, 25 Oct 2017 22:38:54 +0100 10 | 11 | com.github.nick92.coffee (1.0.12~ubuntu17.10) artful; urgency=medium 12 | 13 | * fix settings window not showing on button place 14 | 15 | -- Nick Wilkins Wed, 11 Oct 2017 22:38:54 +0100 16 | 17 | com.github.nick92.coffee (1.0.12~ubuntu17.04) zesty; urgency=medium 18 | 19 | * fix settings window not showing on button place 20 | 21 | -- Nick Wilkins Tue, 10 Oct 2017 22:38:54 +0100 22 | 23 | com.github.nick92.coffee (1.0.12~ubuntu16.10) xenial; urgency=medium 24 | 25 | * fix settings window not showing on button place 26 | 27 | -- Nick Wilkins Tue, 10 Oct 2017 22:38:54 +0100 28 | 29 | com.github.nick92.coffee (1.0.11~ubuntu17.10) artful; urgency=medium 30 | 31 | * keep depriciated screen location for now 32 | 33 | -- Nick Wilkins Fri, 06 Oct 2017 22:38:54 +0100 34 | 35 | com.github.nick92.coffee (1.0.11~ubuntu17.04) zesty; urgency=medium 36 | 37 | * keep depriciated screen location for now 38 | 39 | -- Nick Wilkins Tue, 10 Oct 2017 22:38:54 +0100 40 | 41 | com.github.nick92.coffee (1.0.11~ubuntu16.10) xenial; urgency=medium 42 | 43 | * keep depriciated screen location for now 44 | 45 | -- Nick Wilkins Tue, 10 Oct 2017 22:38:54 +0100 46 | 47 | com.github.nick92.coffee (1.0.10~ubuntu17.10) artful; urgency=medium 48 | 49 | * update Gdk width and height values to support later Gdk versions 50 | 51 | -- Nick Wilkins Fri, 06 Oct 2017 22:38:54 +0100 52 | 53 | com.github.nick92.coffee (1.0.9~ubuntu17.10) artful; urgency=medium 54 | 55 | * initial release for artful 56 | 57 | -- Nick Wilkins Thu, 05 Oct 2017 22:38:54 +0100 58 | 59 | com.github.nick92.coffee (1.0.9) xenial; urgency=medium 60 | 61 | * add close icon to top bar 62 | * open links in default browser 63 | 64 | -- Nick Wilkins Thu, 05 Oct 2017 13:38:54 +0100 65 | 66 | com.github.nick92.coffee (1.0.8) xenial; urgency=medium 67 | 68 | * remove warnings from CoffeeBar 69 | 70 | -- Nick Wilkins Thu, 28 Sep 2017 13:38:54 +0100 71 | 72 | 73 | com.github.nick92.coffee (1.0.7) xenial; urgency=medium 74 | 75 | * fix initial load issue with location 76 | * add local checked icon instead of using system 77 | 78 | -- Nick Wilkins Tue, 26 Sep 2017 13:38:54 +0100 79 | 80 | 81 | com.github.nick92.coffee (1.0.6) xenial; urgency=medium 82 | 83 | * fix debian config 84 | 85 | -- Nick Wilkins Tue, 26 Sep 2017 13:38:54 +0100 86 | 87 | 88 | com.github.nick92.coffee (1.0.5) xenial; urgency=medium 89 | 90 | * change appdata colour scheme 91 | 92 | -- Nick Wilkins Mon, 25 Sep 2017 13:38:54 +0100 93 | 94 | 95 | com.github.nick92.coffee (1.0.4) xenial; urgency=medium 96 | 97 | * remove keybinder and notify deps in control file 98 | 99 | -- Nick Wilkins Mon, 25 Sep 2017 13:38:54 +0100 100 | 101 | 102 | com.github.nick92.coffee (1.0.3) xenial; urgency=medium 103 | 104 | * remove keybinder functionality 105 | * remove notification on startup 106 | 107 | -- Nick Wilkins Sun, 24 Sep 2017 13:38:54 +0100 108 | 109 | 110 | com.github.nick92.coffee (1.0.2) xenial; urgency=medium 111 | 112 | * change of desktop and executable name 113 | 114 | -- Nick Wilkins Fri, 22 Sep 2017 13:38:54 +0100 115 | 116 | 117 | com.github.nick92.coffee (1.0.1) xenial; urgency=medium 118 | 119 | * change of desktop and executable name 120 | 121 | -- Nick Wilkins Fri, 22 Sep 2017 13:38:54 +0100 122 | 123 | 124 | com.github.nick92.coffee (1.0.1) xenial; urgency=medium 125 | 126 | * change of desktop and executable name 127 | 128 | -- Nick Wilkins Fri, 22 Sep 2017 13:38:54 +0100 129 | 130 | 131 | com.github.nick92.coffee (1.0.0) xenial; urgency=medium 132 | 133 | * release for elementary 134 | 135 | -- Nick Wilkins Fri, 22 Sep 2017 13:38:54 +0100 136 | 137 | com.github.nick92.coffee (0.0.3) xenial; urgency=medium 138 | 139 | * remove ability to disable news or weather 140 | * fix the new york times news feed 141 | * remove general settings 142 | * async added to get news and weather 143 | 144 | -- Nick Wilkins Fri, 22 Sep 2017 13:38:54 +0100 145 | 146 | 147 | com.github.nick92.coffee (0.0.2) xenial; urgency=medium 148 | 149 | * edit selected news icon. 150 | * change refresh icon 151 | * set settings window to be larger 152 | 153 | -- Nick Wilkins Thu, 21 Sep 2017 10:38:54 +0100 154 | 155 | 156 | com.github.nick92.coffee (0.0.1) xenial; urgency=medium 157 | 158 | * Initial Release. 159 | 160 | -- Nick Wilkins Wed, 20 Sep 2017 10:38:54 +0100 161 | -------------------------------------------------------------------------------- /debian/compat: -------------------------------------------------------------------------------- 1 | 9 2 | -------------------------------------------------------------------------------- /debian/control: -------------------------------------------------------------------------------- 1 | Source: com.github.nick92.coffee 2 | Section: x11 3 | Priority: optional 4 | Maintainer: Nick Wilkins 5 | Build-Depends: debhelper (>= 9), 6 | libglib2.0-dev, 7 | libgeoclue-2-dev, 8 | libgee-0.8-dev, 9 | libgtk-3-dev, 10 | libgeocode-glib-dev, 11 | libwebkit2gtk-4.0-dev, 12 | libsoup2.4-dev, 13 | libjson-glib-dev, 14 | valac, 15 | meson 16 | Standards-Version: 3.9.6 17 | 18 | Package: com.github.nick92.coffee 19 | Architecture: any 20 | Depends: ${misc:Depends}, ${shlibs:Depends}, geoclue-2.0 21 | Description: Keep up with current news and weather with Coffee 22 | Launch Coffee with a single key press from anywhere 23 | -------------------------------------------------------------------------------- /debian/copyright: -------------------------------------------------------------------------------- 1 | Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ 2 | Upstream-Name: com.github.nick92.coffee-news 3 | Source: https//github.com/nick92/coffee 4 | 5 | Files: * 6 | Copyright: 2017 Nick Wilkins 7 | License: GPL-3.0+ 8 | 9 | Files: debian/* 10 | Copyright: 2017 nick 11 | License: GPL-3.0+ 12 | 13 | License: GPL-3.0+ 14 | This program is free software: you can redistribute it and/or modify 15 | it under the terms of the GNU General Public License as published by 16 | the Free Software Foundation, either version 3 of the License, or 17 | (at your option) any later version. 18 | . 19 | This package is distributed in the hope that it will be useful, 20 | but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | GNU General Public License for more details. 23 | . 24 | You should have received a copy of the GNU General Public License 25 | along with this program. If not, see . 26 | . 27 | On Debian systems, the complete text of the GNU General 28 | Public License version 3 can be found in "/usr/share/common-licenses/GPL-3". 29 | 30 | # Please also look if there are files or directories which have a 31 | # different copyright/license attached and list them here. 32 | # Please avoid picking licenses with terms that are more restrictive than the 33 | # packaged work, as it may make Debian's contributions unacceptable upstream. 34 | -------------------------------------------------------------------------------- /debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | 3 | %: 4 | dh $@ 5 | 6 | 7 | override_dh_auto_clean: 8 | rm -rf debian/build 9 | 10 | override_dh_auto_configure: 11 | mkdir -p debian/build 12 | cd debian/build && meson --prefix=/usr ../.. 13 | 14 | override_dh_auto_build: 15 | cd debian/build && ninja -v 16 | 17 | override_dh_install: 18 | cd debian/build && DESTDIR=${CURDIR}/debian/com.github.nick92.coffee ninja install 19 | 20 | override_dh_shlibdeps: 21 | dh_shlibdeps --dpkg-shlibdeps-params=--ignore-missing-info 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /debian/source/format: -------------------------------------------------------------------------------- 1 | 3.0 (native) 2 | -------------------------------------------------------------------------------- /deps.sh: -------------------------------------------------------------------------------- 1 | sudo apt install libglib2.0-dev \ 2 | libgtk-3-dev \ 3 | libjson-glib-dev \ 4 | libsoup2.4-dev \ 5 | libgee-0.8-dev \ 6 | libgeocode-glib-dev \ 7 | libgeoclue-2-dev \ 8 | meson \ 9 | valac \ 10 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | bower_components -------------------------------------------------------------------------------- /docs/.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: node_js 3 | node_js: 4 | - "node" 5 | install: npm install 6 | script: 7 | - npm test 8 | - gulp 9 | cache: 10 | directories: 11 | - node_modules 12 | -------------------------------------------------------------------------------- /docs/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013-2017 Blackrock Digital LLC 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # [Start Bootstrap - New Age](https://startbootstrap.com/template-overviews/new-age/) 2 | 3 | [New Age](http://startbootstrap.com/template-overviews/new-age/) is a web app landing page theme for [Bootstrap](http://getbootstrap.com/) created by [Start Bootstrap](http://startbootstrap.com/). 4 | 5 | ## Preview 6 | 7 | [![New Age Preview](https://startbootstrap.com/assets/img/templates/new-age.jpg)](https://blackrockdigital.github.io/startbootstrap-new-age/) 8 | 9 | **[View Live Preview](https://blackrockdigital.github.io/startbootstrap-new-age/)** 10 | 11 | ## Status 12 | 13 | [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/BlackrockDigital/startbootstrap-new-age/master/LICENSE) 14 | [![npm version](https://img.shields.io/npm/v/startbootstrap-new-age.svg)](https://www.npmjs.com/package/startbootstrap-new-age) 15 | [![Build Status](https://travis-ci.org/BlackrockDigital/startbootstrap-new-age.svg?branch=master)](https://travis-ci.org/BlackrockDigital/startbootstrap-new-age) 16 | [![dependencies Status](https://david-dm.org/BlackrockDigital/startbootstrap-new-age/status.svg)](https://david-dm.org/BlackrockDigital/startbootstrap-new-age) 17 | [![devDependencies Status](https://david-dm.org/BlackrockDigital/startbootstrap-new-age/dev-status.svg)](https://david-dm.org/BlackrockDigital/startbootstrap-new-age?type=dev) 18 | 19 | ## Download and Installation 20 | 21 | To begin using this template, choose one of the following options to get started: 22 | * [Download the latest release on Start Bootstrap](https://startbootstrap.com/template-overviews/new-age/) 23 | * Install via npm: `npm i startbootstrap-new-age` 24 | * Clone the repo: `git clone https://github.com/BlackrockDigital/startbootstrap-new-age.git` 25 | * [Fork, Clone, or Download on GitHub](https://github.com/BlackrockDigital/startbootstrap-new-age) 26 | 27 | ## Usage 28 | 29 | ### Basic Usage 30 | 31 | After downloading, simply edit the HTML and CSS files included with the template in your favorite text editor to make changes. These are the only files you need to worry about, you can ignore everything else! To preview the changes you make to the code, you can open the `index.html` file in your web browser. 32 | 33 | ### Advanced Usage 34 | 35 | After installation, run `npm install` and then run `gulp dev` which will open up a preview of the template in your default browser, watch for changes to core template files, and live reload the browser when changes are saved. You can view the `gulpfile.js` to see which tasks are included with the dev environment. 36 | 37 | #### Gulp Tasks 38 | 39 | - `gulp` the default task that builds everything 40 | - `gulp dev` browserSync opens the project in your default browser and live reloads when changes are made 41 | - `gulp sass` compiles SCSS files into CSS 42 | - `gulp minify-css` minifies the compiled CSS file 43 | - `gulp minify-js` minifies the themes JS file 44 | - `gulp copy` copies dependencies from node_modules to the vendor directory 45 | 46 | ## Bugs and Issues 47 | 48 | Have a bug or an issue with this template? [Open a new issue](https://github.com/BlackrockDigital/startbootstrap-new-age/issues) here on GitHub or leave a comment on the [template overview page at Start Bootstrap](http://startbootstrap.com/template-overviews/new-age/). 49 | 50 | ## Custom Builds 51 | 52 | You can hire Start Bootstrap to create a custom build of any template, or create something from scratch using Bootstrap. For more information, visit the **[custom design services page](https://startbootstrap.com/bootstrap-design-services/)**. 53 | 54 | ## About 55 | 56 | Start Bootstrap is an open source library of free Bootstrap templates and themes. All of the free templates and themes on Start Bootstrap are released under the MIT license, which means you can use them for any purpose, even for commercial projects. 57 | 58 | * https://startbootstrap.com 59 | * https://twitter.com/SBootstrap 60 | 61 | Start Bootstrap was created by and is maintained by **[David Miller](http://davidmiller.io/)**, Owner of [Blackrock Digital](http://blackrockdigital.io/). 62 | 63 | * http://davidmiller.io 64 | * https://twitter.com/davidmillerskt 65 | * https://github.com/davidtmiller 66 | 67 | Start Bootstrap is based on the [Bootstrap](http://getbootstrap.com/) framework created by [Mark Otto](https://twitter.com/mdo) and [Jacob Thorton](https://twitter.com/fat). 68 | 69 | ## Copyright and License 70 | 71 | Copyright 2013-2017 Blackrock Digital LLC. Code released under the [MIT](https://github.com/BlackrockDigital/startbootstrap-new-age/blob/gh-pages/LICENSE) license. 72 | -------------------------------------------------------------------------------- /docs/css/new-age.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Start Bootstrap - New Age v4.0.0-beta (https://startbootstrap.com/template-overviews/new-age) 3 | * Copyright 2013-2017 Start Bootstrap 4 | * Licensed under MIT (https://github.com/BlackrockDigital/startbootstrap-new-age/blob/master/LICENSE) 5 | */body,html{width:100%;height:100%}body{font-family:Muli,Helvetica,Arial,sans-serif}a{color:#fdcc52;-webkit-transition:all .35s;-moz-transition:all .35s;transition:all .35s}a:focus,a:hover{color:#fcbd20}hr{max-width:100px;margin:25px auto 0;border-width:1px;border-color:rgba(34,34,34,.1)}hr.light{border-color:#fff}h1,h2,h3,h4,h5,h6{font-family:Catamaran,Helvetica,Arial,sans-serif;font-weight:200;letter-spacing:1px}p{font-size:18px;line-height:1.5;margin-bottom:20px}section{padding:100px 0}section h2{font-size:50px}#mainNav{border-color:rgba(34,34,34,.05);background-color:#fff;-webkit-transition:all .35s;-moz-transition:all .35s;transition:all .35s;font-family:Catamaran,Helvetica,Arial,sans-serif;font-weight:200;letter-spacing:1px}#mainNav .navbar-brand{color:#fdcc52;font-family:Catamaran,Helvetica,Arial,sans-serif;font-weight:200;letter-spacing:1px}#mainNav .navbar-brand:focus,#mainNav .navbar-brand:hover{color:#fcbd20}#mainNav .navbar-toggler{font-size:12px;padding:8px 10px;color:#222}#mainNav .navbar-nav>li>a{font-size:11px;font-family:Lato,Helvetica,Arial,sans-serif;letter-spacing:2px;text-transform:uppercase}#mainNav .navbar-nav>li>a.active{color:#fdcc52!important;background-color:transparent}#mainNav .navbar-nav>li>a.active:hover{background-color:transparent}#mainNav .navbar-nav>li>a,#mainNav .navbar-nav>li>a:focus{color:#222}#mainNav .navbar-nav>li>a:focus:hover,#mainNav .navbar-nav>li>a:hover{color:#fdcc52}@media (min-width:992px){#mainNav{border-color:transparent;background-color:transparent}#mainNav .navbar-brand{color:fade(white,70%)}#mainNav .navbar-brand:focus,#mainNav .navbar-brand:hover{color:#fff}#mainNav .navbar-nav>li>a,#mainNav .navbar-nav>li>a:focus{color:rgba(255,255,255,.7)}#mainNav .navbar-nav>li>a:focus:hover,#mainNav .navbar-nav>li>a:hover{color:#fff}#mainNav.navbar-shrink{border-color:rgba(34,34,34,.1);background-color:#fff}#mainNav.navbar-shrink .navbar-brand{color:#222}#mainNav.navbar-shrink .navbar-brand:focus,#mainNav.navbar-shrink .navbar-brand:hover{color:#fdcc52}#mainNav.navbar-shrink .navbar-nav>li>a,#mainNav.navbar-shrink .navbar-nav>li>a:focus{color:#222}#mainNav.navbar-shrink .navbar-nav>li>a:focus:hover,#mainNav.navbar-shrink .navbar-nav>li>a:hover{color:#fdcc52}}header.masthead{position:relative;width:100%;padding-top:150px;padding-bottom:100px;color:#fff;background:url(../img/bg-pattern.png),#7b4397;background:url(../img/bg-pattern.png),-webkit-linear-gradient(to left,#7b4397,#dc2430);background:url(../img/bg-pattern.png),linear-gradient(to left,#7b4397,#dc2430)}header.masthead .header-content{max-width:500px;margin-bottom:100px;text-align:center}header.masthead .header-content h1{font-size:30px}header.masthead .device-container{max-width:325px;margin-right:auto;margin-left:auto}header.masthead .device-container .screen img{border-radius:3px}@media (min-width:992px){header.masthead{height:100vh;min-height:775px;padding-top:0;padding-bottom:0}header.masthead .header-content{margin-bottom:0;text-align:left}header.masthead .header-content h1{font-size:50px}header.masthead .device-container{max-width:325px}}section.download{position:relative;padding:150px 0}section.download h2{font-size:50px;margin-top:0}section.download .badges .badge-link{display:block;margin-bottom:25px}section.download .badges .badge-link:last-child{margin-bottom:0}section.download .badges .badge-link img{height:60px}@media (min-width:768px){section.download .badges .badge-link{display:inline-block;margin-bottom:0}}@media (min-width:768px){section.download h2{font-size:70px}}section.features .section-heading{margin-bottom:100px}section.features .section-heading h2{margin-top:0}section.features .section-heading p{margin-bottom:0}section.features .device-container,section.features .feature-item{max-width:325px;margin:0 auto}section.features .device-container{margin-bottom:100px}@media (min-width:992px){section.features .device-container{margin-bottom:0}}section.features .feature-item{padding-top:50px;padding-bottom:50px;text-align:center}section.features .feature-item h3{font-size:30px}section.features .feature-item i{font-size:80px;display:block;margin-bottom:15px;background:-webkit-linear-gradient(to left,#7b4397,#dc2430);background:linear-gradient(to left,#7b4397,#dc2430);-webkit-background-clip:text;-webkit-text-fill-color:transparent}section.cta{position:relative;padding:250px 0;background-image:url(../img/bg-cta.jpg);background-position:center;-webkit-background-size:cover;-moz-background-size:cover;-o-background-size:cover;background-size:cover}section.cta .cta-content{position:relative;z-index:1}section.cta .cta-content h2{font-size:50px;max-width:450px;margin-top:0;margin-bottom:25px;color:#fff}@media (min-width:768px){section.cta .cta-content h2{font-size:80px}}section.cta .overlay{position:absolute;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,.5)}section.contact{text-align:center}section.contact h2{margin-top:0;margin-bottom:25px}section.contact h2 i{color:#dd4b39}section.contact ul.list-social{margin-bottom:0}section.contact ul.list-social li a{font-size:40px;line-height:80px;display:block;width:80px;height:80px;color:#fff;border-radius:100%}section.contact ul.list-social li.social-twitter a{background-color:#1da1f2}section.contact ul.list-social li.social-twitter a:hover{background-color:#0d95e8}section.contact ul.list-social li.social-facebook a{background-color:#3b5998}section.contact ul.list-social li.social-facebook a:hover{background-color:#344e86}section.contact ul.list-social li.social-google-plus a{background-color:#dd4b39}section.contact ul.list-social li.social-google-plus a:hover{background-color:#d73925}footer{padding:25px 0;text-align:center;color:rgba(255,255,255,.3);background-color:#222}footer p{font-size:12px;margin:0}footer ul{margin-bottom:0}footer ul li a{font-size:12px;color:rgba(255,255,255,.3)}footer ul li a.active,footer ul li a:active,footer ul li a:focus,footer ul li a:hover{text-decoration:none}.bg-primary{background:#fdcc52;background:-webkit-linear-gradient(#fdcc52,#fdc539);background:linear-gradient(#fdcc52,#fdc539)}.text-primary{color:#fdcc52}.no-gutter>[class*=col-]{padding-right:0;padding-left:0}.btn-outline{color:#fff;border:1px solid;border-color:#fff}.btn-outline.active,.btn-outline:active,.btn-outline:focus,.btn-outline:hover{color:#fff;border-color:#fdcc52;background-color:#fdcc52}.btn{border-radius:300px;font-family:Lato,Helvetica,Arial,sans-serif;letter-spacing:2px;text-transform:uppercase}.btn-xl{font-size:11px;padding:15px 45px} -------------------------------------------------------------------------------- /docs/gulpfile.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'); 2 | var sass = require('gulp-sass'); 3 | var browserSync = require('browser-sync').create(); 4 | var header = require('gulp-header'); 5 | var cleanCSS = require('gulp-clean-css'); 6 | var rename = require("gulp-rename"); 7 | var uglify = require('gulp-uglify'); 8 | var pkg = require('./package.json'); 9 | 10 | // Set the banner content 11 | var banner = ['/*!\n', 12 | ' * Start Bootstrap - <%= pkg.title %> v<%= pkg.version %> (<%= pkg.homepage %>)\n', 13 | ' * Copyright 2013-' + (new Date()).getFullYear(), ' <%= pkg.author %>\n', 14 | ' * Licensed under <%= pkg.license %> (https://github.com/BlackrockDigital/<%= pkg.name %>/blob/master/LICENSE)\n', 15 | ' */\n', 16 | '' 17 | ].join(''); 18 | 19 | // Compiles SCSS files from /scss into /css 20 | gulp.task('sass', function() { 21 | return gulp.src('scss/new-age.scss') 22 | .pipe(sass()) 23 | .pipe(header(banner, { 24 | pkg: pkg 25 | })) 26 | .pipe(gulp.dest('css')) 27 | .pipe(browserSync.reload({ 28 | stream: true 29 | })) 30 | }); 31 | 32 | // Minify compiled CSS 33 | gulp.task('minify-css', ['sass'], function() { 34 | return gulp.src('css/new-age.css') 35 | .pipe(cleanCSS({ 36 | compatibility: 'ie8' 37 | })) 38 | .pipe(rename({ 39 | suffix: '.min' 40 | })) 41 | .pipe(gulp.dest('css')) 42 | .pipe(browserSync.reload({ 43 | stream: true 44 | })) 45 | }); 46 | 47 | // Minify custom JS 48 | gulp.task('minify-js', function() { 49 | return gulp.src('js/new-age.js') 50 | .pipe(uglify()) 51 | .pipe(header(banner, { 52 | pkg: pkg 53 | })) 54 | .pipe(rename({ 55 | suffix: '.min' 56 | })) 57 | .pipe(gulp.dest('js')) 58 | .pipe(browserSync.reload({ 59 | stream: true 60 | })) 61 | }); 62 | 63 | // Copy vendor files from /node_modules into /vendor 64 | // NOTE: requires `npm install` before running! 65 | gulp.task('copy', function() { 66 | gulp.src([ 67 | 'node_modules/bootstrap/dist/**/*', 68 | '!**/npm.js', 69 | '!**/bootstrap-theme.*', 70 | '!**/*.map' 71 | ]) 72 | .pipe(gulp.dest('vendor/bootstrap')) 73 | 74 | gulp.src(['node_modules/jquery/dist/jquery.js', 'node_modules/jquery/dist/jquery.min.js']) 75 | .pipe(gulp.dest('vendor/jquery')) 76 | 77 | gulp.src(['node_modules/popper.js/dist/umd/popper.js', 'node_modules/popper.js/dist/umd/popper.min.js']) 78 | .pipe(gulp.dest('vendor/popper')) 79 | 80 | gulp.src(['node_modules/jquery.easing/*.js']) 81 | .pipe(gulp.dest('vendor/jquery-easing')) 82 | 83 | gulp.src(['node_modules/simple-line-icons/*/*']) 84 | .pipe(gulp.dest('vendor/simple-line-icons')) 85 | 86 | 87 | gulp.src([ 88 | 'node_modules/font-awesome/**', 89 | '!node_modules/font-awesome/**/*.map', 90 | '!node_modules/font-awesome/.npmignore', 91 | '!node_modules/font-awesome/*.txt', 92 | '!node_modules/font-awesome/*.md', 93 | '!node_modules/font-awesome/*.json' 94 | ]) 95 | .pipe(gulp.dest('vendor/font-awesome')) 96 | }) 97 | 98 | // Default task 99 | gulp.task('default', ['sass', 'minify-css', 'minify-js', 'copy']); 100 | 101 | // Configure the browserSync task 102 | gulp.task('browserSync', function() { 103 | browserSync.init({ 104 | server: { 105 | baseDir: '' 106 | }, 107 | }) 108 | }) 109 | 110 | // Dev task with browserSync 111 | gulp.task('dev', ['browserSync', 'sass', 'minify-css', 'minify-js'], function() { 112 | gulp.watch('scss/*.scss', ['sass']); 113 | gulp.watch('css/*.css', ['minify-css']); 114 | gulp.watch('js/*.js', ['minify-js']); 115 | // Reloads the browser whenever HTML or JS files change 116 | gulp.watch('*.html', browserSync.reload); 117 | gulp.watch('js/**/*.js', browserSync.reload); 118 | }); 119 | -------------------------------------------------------------------------------- /docs/img/coffee.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick92/coffee/2bae1178be34bbf72a92143a4534ac2e739b4a8d/docs/img/coffee.ico -------------------------------------------------------------------------------- /docs/img/settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick92/coffee/2bae1178be34bbf72a92143a4534ac2e739b4a8d/docs/img/settings.png -------------------------------------------------------------------------------- /docs/js/new-age.js: -------------------------------------------------------------------------------- 1 | (function($) { 2 | "use strict"; // Start of use strict 3 | 4 | // Smooth scrolling using jQuery easing 5 | $('a.js-scroll-trigger[href*="#"]:not([href="#"])').click(function() { 6 | if (location.pathname.replace(/^\//, '') == this.pathname.replace(/^\//, '') && location.hostname == this.hostname) { 7 | var target = $(this.hash); 8 | target = target.length ? target : $('[name=' + this.hash.slice(1) + ']'); 9 | if (target.length) { 10 | $('html, body').animate({ 11 | scrollTop: (target.offset().top - 48) 12 | }, 1000, "easeInOutExpo"); 13 | return false; 14 | } 15 | } 16 | }); 17 | 18 | // Closes responsive menu when a scroll trigger link is clicked 19 | $('.js-scroll-trigger').click(function() { 20 | $('.navbar-collapse').collapse('hide'); 21 | }); 22 | 23 | // Activate scrollspy to add active class to navbar items on scroll 24 | $('body').scrollspy({ 25 | target: '#mainNav', 26 | offset: 54 27 | }); 28 | 29 | // Collapse the navbar when page is scrolled 30 | $(window).scroll(function() { 31 | if ($("#mainNav").offset().top > 100) { 32 | $("#mainNav").addClass("navbar-shrink"); 33 | } else { 34 | $("#mainNav").removeClass("navbar-shrink"); 35 | } 36 | }); 37 | 38 | })(jQuery); // End of use strict 39 | -------------------------------------------------------------------------------- /docs/js/new-age.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Start Bootstrap - New Age v4.0.0-beta (https://startbootstrap.com/template-overviews/new-age) 3 | * Copyright 2013-2017 Start Bootstrap 4 | * Licensed under MIT (https://github.com/BlackrockDigital/startbootstrap-new-age/blob/master/LICENSE) 5 | */ 6 | !function(a){"use strict";a('a.js-scroll-trigger[href*="#"]:not([href="#"])').click(function(){if(location.pathname.replace(/^\//,"")==this.pathname.replace(/^\//,"")&&location.hostname==this.hostname){var e=a(this.hash);if((e=e.length?e:a("[name="+this.hash.slice(1)+"]")).length)return a("html, body").animate({scrollTop:e.offset().top-48},1e3,"easeInOutExpo"),!1}}),a(".js-scroll-trigger").click(function(){a(".navbar-collapse").collapse("hide")}),a("body").scrollspy({target:"#mainNav",offset:54}),a(window).scroll(function(){a("#mainNav").offset().top>100?a("#mainNav").addClass("navbar-shrink"):a("#mainNav").removeClass("navbar-shrink")})}(jQuery); -------------------------------------------------------------------------------- /docs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "New Age", 3 | "name": "startbootstrap-new-age", 4 | "version": "4.0.0-beta", 5 | "description": "A one page app landing page HTML theme for Bootstrap.", 6 | "keywords": [ 7 | "css", 8 | "sass", 9 | "html", 10 | "responsive", 11 | "theme", 12 | "template" 13 | ], 14 | "homepage": "https://startbootstrap.com/template-overviews/new-age", 15 | "bugs": { 16 | "url": "https://github.com/BlackrockDigital/startbootstrap-new-age/issues", 17 | "email": "feedback@startbootstrap.com" 18 | }, 19 | "license": "MIT", 20 | "author": "Start Bootstrap", 21 | "contributors": [ 22 | "David Miller (http://davidmiller.io/)" 23 | ], 24 | "repository": { 25 | "type": "git", 26 | "url": "https://github.com/BlackrockDigital/startbootstrap-new-age.git" 27 | }, 28 | "dependencies": { 29 | "bootstrap": "^4.0.0-beta", 30 | "font-awesome": "4.7.0", 31 | "jquery": "^3.2.1", 32 | "jquery.easing": "^1.4.1", 33 | "popper.js": "1.12.3", 34 | "simple-line-icons": "2.4.1" 35 | }, 36 | "devDependencies": { 37 | "browser-sync": "2.18.13", 38 | "gulp": "^3.9.1", 39 | "gulp-clean-css": "3.7.0", 40 | "gulp-header": "1.8.9", 41 | "gulp-rename": "^1.2.2", 42 | "gulp-sass": "^3.1.0", 43 | "gulp-uglify": "3.0.0" 44 | } 45 | } -------------------------------------------------------------------------------- /docs/scss/_bootstrap-overrides.scss: -------------------------------------------------------------------------------- 1 | // Bootstrap overrides for this template 2 | .bg-primary { 3 | background: $theme-primary; 4 | background: -webkit-linear-gradient($theme-primary, darken($theme-primary, 5%)); 5 | background: linear-gradient($theme-primary, darken($theme-primary, 5%)); 6 | } 7 | 8 | .text-primary { 9 | color: $theme-primary; 10 | } 11 | 12 | .no-gutter > [class*='col-'] { 13 | padding-right: 0; 14 | padding-left: 0; 15 | } 16 | 17 | .btn-outline { 18 | color: white; 19 | border: 1px solid; 20 | border-color: white; 21 | &:hover, 22 | &:focus, 23 | &:active, 24 | &.active { 25 | color: white; 26 | border-color: $theme-primary; 27 | background-color: $theme-primary; 28 | } 29 | } 30 | 31 | .btn { 32 | border-radius: 300px; 33 | @include alt-font; 34 | } 35 | 36 | .btn-xl { 37 | font-size: 11px; 38 | padding: 15px 45px; 39 | } 40 | -------------------------------------------------------------------------------- /docs/scss/_contact.scss: -------------------------------------------------------------------------------- 1 | // Styling for the download section 2 | section.contact { 3 | text-align: center; 4 | h2 { 5 | margin-top: 0; 6 | margin-bottom: 25px; 7 | i { 8 | color: $brand-google-plus; 9 | } 10 | } 11 | ul.list-social { 12 | margin-bottom: 0; 13 | li { 14 | a { 15 | font-size: 40px; 16 | line-height: 80px; 17 | display: block; 18 | width: 80px; 19 | height: 80px; 20 | color: white; 21 | border-radius: 100%; 22 | } 23 | &.social-twitter { 24 | a { 25 | background-color: $brand-twitter; 26 | &:hover { 27 | background-color: darken($brand-twitter, 5%); 28 | } 29 | } 30 | } 31 | &.social-facebook { 32 | a { 33 | background-color: $brand-facebook; 34 | &:hover { 35 | background-color: darken($brand-facebook, 5%); 36 | } 37 | } 38 | } 39 | &.social-google-plus { 40 | a { 41 | background-color: $brand-google-plus; 42 | &:hover { 43 | background-color: darken($brand-google-plus, 5%); 44 | } 45 | } 46 | } 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /docs/scss/_cta.scss: -------------------------------------------------------------------------------- 1 | // Styling for the call to action section 2 | section.cta { 3 | position: relative; 4 | padding: 250px 0; 5 | background-image: url('../img/bg-cta.jpg'); 6 | background-position: center; 7 | @include background-cover; 8 | .cta-content { 9 | position: relative; 10 | z-index: 1; 11 | h2 { 12 | font-size: 50px; 13 | max-width: 450px; 14 | margin-top: 0; 15 | margin-bottom: 25px; 16 | color: white; 17 | } 18 | @media (min-width: 768px) { 19 | h2 { 20 | font-size: 80px; 21 | } 22 | } 23 | } 24 | .overlay { 25 | position: absolute; 26 | top: 0; 27 | left: 0; 28 | width: 100%; 29 | height: 100%; 30 | background-color: fade-out(black, .5); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /docs/scss/_download.scss: -------------------------------------------------------------------------------- 1 | // Styling for the download section 2 | section.download { 3 | position: relative; 4 | padding: 150px 0; 5 | h2 { 6 | font-size: 50px; 7 | margin-top: 0; 8 | } 9 | .badges { 10 | .badge-link { 11 | display: block; 12 | margin-bottom: 25px; 13 | &:last-child { 14 | margin-bottom: 0; 15 | } 16 | img { 17 | height: 60px; 18 | } 19 | @media(min-width: 768px) { 20 | display: inline-block; 21 | margin-bottom: 0; 22 | } 23 | } 24 | } 25 | @media(min-width: 768px) { 26 | h2 { 27 | font-size: 70px; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /docs/scss/_features.scss: -------------------------------------------------------------------------------- 1 | // Styling for the features section 2 | section.features { 3 | .section-heading { 4 | margin-bottom: 100px; 5 | h2 { 6 | margin-top: 0; 7 | } 8 | p { 9 | margin-bottom: 0; 10 | } 11 | } 12 | .device-container, 13 | .feature-item { 14 | max-width: 325px; 15 | margin: 0 auto; 16 | } 17 | .device-container { 18 | margin-bottom: 100px; 19 | @media(min-width: 992px) { 20 | margin-bottom: 0; 21 | } 22 | } 23 | .feature-item { 24 | padding-top: 50px; 25 | padding-bottom: 50px; 26 | text-align: center; 27 | h3 { 28 | font-size: 30px; 29 | } 30 | i { 31 | font-size: 80px; 32 | display: block; 33 | margin-bottom: 15px; 34 | background: -webkit-linear-gradient(to left, $theme-secondary, $theme-tertiary); 35 | background: linear-gradient(to left, $theme-secondary, $theme-tertiary); 36 | -webkit-background-clip: text; 37 | -webkit-text-fill-color: transparent; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /docs/scss/_footer.scss: -------------------------------------------------------------------------------- 1 | // Styling for the footer 2 | footer { 3 | padding: 25px 0; 4 | text-align: center; 5 | color: fade-out(white, .7); 6 | background-color: $gray-darker; 7 | p { 8 | font-size: 12px; 9 | margin: 0; 10 | } 11 | ul { 12 | margin-bottom: 0; 13 | li { 14 | a { 15 | font-size: 12px; 16 | color: fade-out(white, .7); 17 | &:hover, 18 | &:focus, 19 | &:active, 20 | &.active { 21 | text-decoration: none; 22 | } 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /docs/scss/_global.scss: -------------------------------------------------------------------------------- 1 | // Global styling for this template 2 | html, 3 | body { 4 | width: 100%; 5 | height: 100%; 6 | } 7 | 8 | body { 9 | @include body-font; 10 | } 11 | 12 | a { 13 | color: $theme-primary; 14 | @include transition-all; 15 | &:hover, 16 | &:focus { 17 | color: darken($theme-primary, 10%); 18 | } 19 | } 20 | 21 | hr { 22 | max-width: 100px; 23 | margin: 25px auto 0; 24 | border-width: 1px; 25 | border-color: fade-out($gray-darker, .9); 26 | } 27 | 28 | hr.light { 29 | border-color: white; 30 | } 31 | 32 | h1, 33 | h2, 34 | h3, 35 | h4, 36 | h5, 37 | h6 { 38 | @include heading-font; 39 | } 40 | 41 | p { 42 | font-size: 18px; 43 | line-height: 1.5; 44 | margin-bottom: 20px; 45 | } 46 | 47 | section { 48 | padding: 100px 0; 49 | h2 { 50 | font-size: 50px; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /docs/scss/_masthead.scss: -------------------------------------------------------------------------------- 1 | // Styling for the masthead 2 | header.masthead { 3 | position: relative; 4 | 5 | width: 100%; 6 | padding-top: 150px; 7 | padding-bottom: 100px; 8 | 9 | color: white; 10 | background: url('../img/bg-pattern.png'), $theme-secondary; 11 | background: url('../img/bg-pattern.png'), -webkit-linear-gradient(to left, $theme-secondary, $theme-tertiary); 12 | background: url('../img/bg-pattern.png'), linear-gradient(to left, $theme-secondary, $theme-tertiary); 13 | .header-content { 14 | max-width: 500px; 15 | margin-bottom: 100px; 16 | 17 | text-align: center; 18 | h1 { 19 | font-size: 30px; 20 | } 21 | } 22 | .device-container { 23 | max-width: 325px; 24 | margin-right: auto; 25 | margin-left: auto; 26 | .screen img { 27 | border-radius: 3px; 28 | } 29 | } 30 | @media (min-width: 992px) { 31 | height: 100vh; 32 | min-height: 775px; 33 | padding-top: 0; 34 | padding-bottom: 0; 35 | .header-content { 36 | margin-bottom: 0; 37 | 38 | text-align: left; 39 | h1 { 40 | font-size: 50px; 41 | } 42 | } 43 | .device-container { 44 | max-width: 325px; 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /docs/scss/_mixins.scss: -------------------------------------------------------------------------------- 1 | // Mixins 2 | @mixin transition-all() { 3 | -webkit-transition: all .35s; 4 | -moz-transition: all .35s; 5 | transition: all .35s; 6 | } 7 | 8 | @mixin background-cover() { 9 | -webkit-background-size: cover; 10 | -moz-background-size: cover; 11 | -o-background-size: cover; 12 | background-size: cover; 13 | } 14 | 15 | @mixin button-variant($color, $background, $border) { 16 | color: $color; 17 | border-color: $border; 18 | background-color: $background; 19 | &:focus, 20 | &.focus { 21 | color: $color; 22 | border-color: darken($border, 25%); 23 | background-color: darken($background, 10%); 24 | } 25 | &:hover { 26 | color: $color; 27 | border-color: darken($border, 12%); 28 | background-color: darken($background, 10%); 29 | } 30 | &:active, 31 | &.active, 32 | .open > &.dropdown-toggle { 33 | color: $color; 34 | border-color: darken($border, 12%); 35 | background-color: darken($background, 10%); 36 | &:hover, 37 | &:focus, 38 | &.focus { 39 | color: $color; 40 | border-color: darken($border, 25%); 41 | background-color: darken($background, 17%); 42 | } 43 | } 44 | &:active, 45 | &.active, 46 | .open > &.dropdown-toggle { 47 | background-image: none; 48 | } 49 | &.disabled, 50 | &[disabled], 51 | fieldset[disabled] & { 52 | &:hover, 53 | &:focus, 54 | &.focus { 55 | border-color: $border; 56 | background-color: $background; 57 | } 58 | } 59 | .badge { 60 | color: $background; 61 | background-color: $color; 62 | } 63 | } 64 | 65 | @mixin heading-font { 66 | font-family: 'Catamaran', 'Helvetica', 'Arial', 'sans-serif'; 67 | font-weight: 200; 68 | letter-spacing: 1px; 69 | } 70 | 71 | @mixin body-font { 72 | font-family: 'Muli', 'Helvetica', 'Arial', 'sans-serif'; 73 | } 74 | 75 | @mixin alt-font { 76 | font-family: 'Lato', 'Helvetica', 'Arial', 'sans-serif'; 77 | letter-spacing: 2px; 78 | text-transform: uppercase; 79 | } 80 | -------------------------------------------------------------------------------- /docs/scss/_navbar.scss: -------------------------------------------------------------------------------- 1 | // Styling for the navbar 2 | #mainNav { 3 | border-color: fade-out($gray-darker, .95); 4 | background-color: white; 5 | @include transition-all; 6 | @include heading-font; 7 | .navbar-brand { 8 | color: $theme-primary; 9 | @include heading-font; 10 | &:hover, 11 | &:focus { 12 | color: darken($theme-primary, 10%); 13 | } 14 | } 15 | .navbar-toggler { 16 | font-size: 12px; 17 | padding: 8px 10px; 18 | color: $gray-darker; 19 | } 20 | .navbar-nav { 21 | > li { 22 | > a { 23 | font-size: 11px; 24 | @include alt-font; 25 | &.active { 26 | color: $theme-primary !important; 27 | background-color: transparent; 28 | &:hover { 29 | background-color: transparent; 30 | } 31 | } 32 | } 33 | > a, 34 | > a:focus { 35 | color: $gray-darker; 36 | &:hover { 37 | color: $theme-primary; 38 | } 39 | } 40 | } 41 | } 42 | @media (min-width: 992px) { 43 | border-color: transparent; 44 | background-color: transparent; 45 | .navbar-brand { 46 | color: fade(white, 70%); 47 | &:hover, 48 | &:focus { 49 | color: white; 50 | } 51 | } 52 | .navbar-nav > li > a, 53 | .navbar-nav > li > a:focus { 54 | color: fade-out(white, .3); 55 | &:hover { 56 | color: white; 57 | } 58 | } 59 | &.navbar-shrink { 60 | border-color: fade-out($gray-darker, .9); 61 | background-color: white; 62 | .navbar-brand { 63 | color: $gray-darker; 64 | &:hover, 65 | &:focus { 66 | color: $theme-primary; 67 | } 68 | } 69 | .navbar-nav > li > a, 70 | .navbar-nav > li > a:focus { 71 | color: $gray-darker; 72 | &:hover { 73 | color: $theme-primary; 74 | } 75 | } 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /docs/scss/_variables.scss: -------------------------------------------------------------------------------- 1 | // Variables 2 | 3 | // Gray and Brand Colors for use across theme 4 | 5 | $theme-primary: #fdcc52; 6 | $theme-secondary: #7b4397; 7 | $theme-tertiary: #dc2430; 8 | 9 | $gray-base: #000; 10 | $gray-darker: lighten($gray-base, 13.5%); // #222 11 | $gray-dark: lighten($gray-base, 20%); // #333 12 | $gray: lighten($gray-base, 33.5%); // #555 13 | $gray-light: lighten($gray-base, 46.7%); // #777 14 | $gray-lighter: lighten($gray-base, 93.5%); // #eee 15 | 16 | $brand-twitter: #1da1f2; 17 | $brand-facebook: #3b5998; 18 | $brand-google-plus: #dd4b39; -------------------------------------------------------------------------------- /docs/scss/new-age.scss: -------------------------------------------------------------------------------- 1 | @import "variables.scss"; 2 | @import "mixins.scss"; 3 | @import "global.scss"; 4 | @import "navbar.scss"; 5 | @import "masthead.scss"; 6 | @import "download.scss"; 7 | @import "features.scss"; 8 | @import "cta.scss"; 9 | @import "contact.scss"; 10 | @import "footer.scss"; 11 | @import "bootstrap-overrides.scss"; 12 | -------------------------------------------------------------------------------- /docs/vendor/bootstrap/css/bootstrap-reboot.css: -------------------------------------------------------------------------------- 1 | html { 2 | box-sizing: border-box; 3 | font-family: sans-serif; 4 | line-height: 1.15; 5 | -webkit-text-size-adjust: 100%; 6 | -ms-text-size-adjust: 100%; 7 | -ms-overflow-style: scrollbar; 8 | -webkit-tap-highlight-color: transparent; 9 | } 10 | 11 | *, 12 | *::before, 13 | *::after { 14 | box-sizing: inherit; 15 | } 16 | 17 | @-ms-viewport { 18 | width: device-width; 19 | } 20 | 21 | article, aside, dialog, figcaption, figure, footer, header, hgroup, main, nav, section { 22 | display: block; 23 | } 24 | 25 | body { 26 | margin: 0; 27 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; 28 | font-size: 1rem; 29 | font-weight: normal; 30 | line-height: 1.5; 31 | color: #212529; 32 | background-color: #fff; 33 | } 34 | 35 | [tabindex="-1"]:focus { 36 | outline: none !important; 37 | } 38 | 39 | hr { 40 | box-sizing: content-box; 41 | height: 0; 42 | overflow: visible; 43 | } 44 | 45 | h1, h2, h3, h4, h5, h6 { 46 | margin-top: 0; 47 | margin-bottom: .5rem; 48 | } 49 | 50 | p { 51 | margin-top: 0; 52 | margin-bottom: 1rem; 53 | } 54 | 55 | abbr[title], 56 | abbr[data-original-title] { 57 | text-decoration: underline; 58 | -webkit-text-decoration: underline dotted; 59 | text-decoration: underline dotted; 60 | cursor: help; 61 | border-bottom: 0; 62 | } 63 | 64 | address { 65 | margin-bottom: 1rem; 66 | font-style: normal; 67 | line-height: inherit; 68 | } 69 | 70 | ol, 71 | ul, 72 | dl { 73 | margin-top: 0; 74 | margin-bottom: 1rem; 75 | } 76 | 77 | ol ol, 78 | ul ul, 79 | ol ul, 80 | ul ol { 81 | margin-bottom: 0; 82 | } 83 | 84 | dt { 85 | font-weight: bold; 86 | } 87 | 88 | dd { 89 | margin-bottom: .5rem; 90 | margin-left: 0; 91 | } 92 | 93 | blockquote { 94 | margin: 0 0 1rem; 95 | } 96 | 97 | dfn { 98 | font-style: italic; 99 | } 100 | 101 | b, 102 | strong { 103 | font-weight: bolder; 104 | } 105 | 106 | small { 107 | font-size: 80%; 108 | } 109 | 110 | sub, 111 | sup { 112 | position: relative; 113 | font-size: 75%; 114 | line-height: 0; 115 | vertical-align: baseline; 116 | } 117 | 118 | sub { 119 | bottom: -.25em; 120 | } 121 | 122 | sup { 123 | top: -.5em; 124 | } 125 | 126 | a { 127 | color: #007bff; 128 | text-decoration: none; 129 | background-color: transparent; 130 | -webkit-text-decoration-skip: objects; 131 | } 132 | 133 | a:hover { 134 | color: #0056b3; 135 | text-decoration: underline; 136 | } 137 | 138 | a:not([href]):not([tabindex]) { 139 | color: inherit; 140 | text-decoration: none; 141 | } 142 | 143 | a:not([href]):not([tabindex]):focus, a:not([href]):not([tabindex]):hover { 144 | color: inherit; 145 | text-decoration: none; 146 | } 147 | 148 | a:not([href]):not([tabindex]):focus { 149 | outline: 0; 150 | } 151 | 152 | pre, 153 | code, 154 | kbd, 155 | samp { 156 | font-family: monospace, monospace; 157 | font-size: 1em; 158 | } 159 | 160 | pre { 161 | margin-top: 0; 162 | margin-bottom: 1rem; 163 | overflow: auto; 164 | } 165 | 166 | figure { 167 | margin: 0 0 1rem; 168 | } 169 | 170 | img { 171 | vertical-align: middle; 172 | border-style: none; 173 | } 174 | 175 | svg:not(:root) { 176 | overflow: hidden; 177 | } 178 | 179 | a, 180 | area, 181 | button, 182 | [role="button"], 183 | input, 184 | label, 185 | select, 186 | summary, 187 | textarea { 188 | -ms-touch-action: manipulation; 189 | touch-action: manipulation; 190 | } 191 | 192 | table { 193 | border-collapse: collapse; 194 | } 195 | 196 | caption { 197 | padding-top: 0.75rem; 198 | padding-bottom: 0.75rem; 199 | color: #868e96; 200 | text-align: left; 201 | caption-side: bottom; 202 | } 203 | 204 | th { 205 | text-align: left; 206 | } 207 | 208 | label { 209 | display: inline-block; 210 | margin-bottom: .5rem; 211 | } 212 | 213 | button:focus { 214 | outline: 1px dotted; 215 | outline: 5px auto -webkit-focus-ring-color; 216 | } 217 | 218 | input, 219 | button, 220 | select, 221 | optgroup, 222 | textarea { 223 | margin: 0; 224 | font-family: inherit; 225 | font-size: inherit; 226 | line-height: inherit; 227 | } 228 | 229 | button, 230 | input { 231 | overflow: visible; 232 | } 233 | 234 | button, 235 | select { 236 | text-transform: none; 237 | } 238 | 239 | button, 240 | html [type="button"], 241 | [type="reset"], 242 | [type="submit"] { 243 | -webkit-appearance: button; 244 | } 245 | 246 | button::-moz-focus-inner, 247 | [type="button"]::-moz-focus-inner, 248 | [type="reset"]::-moz-focus-inner, 249 | [type="submit"]::-moz-focus-inner { 250 | padding: 0; 251 | border-style: none; 252 | } 253 | 254 | input[type="radio"], 255 | input[type="checkbox"] { 256 | box-sizing: border-box; 257 | padding: 0; 258 | } 259 | 260 | input[type="date"], 261 | input[type="time"], 262 | input[type="datetime-local"], 263 | input[type="month"] { 264 | -webkit-appearance: listbox; 265 | } 266 | 267 | textarea { 268 | overflow: auto; 269 | resize: vertical; 270 | } 271 | 272 | fieldset { 273 | min-width: 0; 274 | padding: 0; 275 | margin: 0; 276 | border: 0; 277 | } 278 | 279 | legend { 280 | display: block; 281 | width: 100%; 282 | max-width: 100%; 283 | padding: 0; 284 | margin-bottom: .5rem; 285 | font-size: 1.5rem; 286 | line-height: inherit; 287 | color: inherit; 288 | white-space: normal; 289 | } 290 | 291 | progress { 292 | vertical-align: baseline; 293 | } 294 | 295 | [type="number"]::-webkit-inner-spin-button, 296 | [type="number"]::-webkit-outer-spin-button { 297 | height: auto; 298 | } 299 | 300 | [type="search"] { 301 | outline-offset: -2px; 302 | -webkit-appearance: none; 303 | } 304 | 305 | [type="search"]::-webkit-search-cancel-button, 306 | [type="search"]::-webkit-search-decoration { 307 | -webkit-appearance: none; 308 | } 309 | 310 | ::-webkit-file-upload-button { 311 | font: inherit; 312 | -webkit-appearance: button; 313 | } 314 | 315 | output { 316 | display: inline-block; 317 | } 318 | 319 | summary { 320 | display: list-item; 321 | } 322 | 323 | template { 324 | display: none; 325 | } 326 | 327 | [hidden] { 328 | display: none !important; 329 | } 330 | /*# sourceMappingURL=bootstrap-reboot.css.map */ -------------------------------------------------------------------------------- /docs/vendor/bootstrap/css/bootstrap-reboot.min.css: -------------------------------------------------------------------------------- 1 | html{box-sizing:border-box;font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;-ms-overflow-style:scrollbar;-webkit-tap-highlight-color:transparent}*,::after,::before{box-sizing:inherit}@-ms-viewport{width:device-width}article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;font-size:1rem;font-weight:400;line-height:1.5;color:#212529;background-color:#fff}[tabindex="-1"]:focus{outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}dfn{font-style:italic}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent;-webkit-text-decoration-skip:objects}a:hover{color:#0056b3;text-decoration:underline}a:not([href]):not([tabindex]){color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus,a:not([href]):not([tabindex]):hover{color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus{outline:0}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg:not(:root){overflow:hidden}[role=button],a,area,button,input,label,select,summary,textarea{-ms-touch-action:manipulation;touch-action:manipulation}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#868e96;text-align:left;caption-side:bottom}th{text-align:left}label{display:inline-block;margin-bottom:.5rem}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}[type=reset],[type=submit],button,html [type=button]{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=date],input[type=datetime-local],input[type=month],input[type=time]{-webkit-appearance:listbox}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item}template{display:none}[hidden]{display:none!important} 2 | /*# sourceMappingURL=bootstrap-reboot.min.css.map */ -------------------------------------------------------------------------------- /docs/vendor/font-awesome/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick92/coffee/2bae1178be34bbf72a92143a4534ac2e739b4a8d/docs/vendor/font-awesome/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /docs/vendor/font-awesome/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick92/coffee/2bae1178be34bbf72a92143a4534ac2e739b4a8d/docs/vendor/font-awesome/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /docs/vendor/font-awesome/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick92/coffee/2bae1178be34bbf72a92143a4534ac2e739b4a8d/docs/vendor/font-awesome/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /docs/vendor/font-awesome/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick92/coffee/2bae1178be34bbf72a92143a4534ac2e739b4a8d/docs/vendor/font-awesome/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /docs/vendor/font-awesome/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick92/coffee/2bae1178be34bbf72a92143a4534ac2e739b4a8d/docs/vendor/font-awesome/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /docs/vendor/font-awesome/less/animated.less: -------------------------------------------------------------------------------- 1 | // Animated Icons 2 | // -------------------------- 3 | 4 | .@{fa-css-prefix}-spin { 5 | -webkit-animation: fa-spin 2s infinite linear; 6 | animation: fa-spin 2s infinite linear; 7 | } 8 | 9 | .@{fa-css-prefix}-pulse { 10 | -webkit-animation: fa-spin 1s infinite steps(8); 11 | animation: fa-spin 1s infinite steps(8); 12 | } 13 | 14 | @-webkit-keyframes fa-spin { 15 | 0% { 16 | -webkit-transform: rotate(0deg); 17 | transform: rotate(0deg); 18 | } 19 | 100% { 20 | -webkit-transform: rotate(359deg); 21 | transform: rotate(359deg); 22 | } 23 | } 24 | 25 | @keyframes fa-spin { 26 | 0% { 27 | -webkit-transform: rotate(0deg); 28 | transform: rotate(0deg); 29 | } 30 | 100% { 31 | -webkit-transform: rotate(359deg); 32 | transform: rotate(359deg); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /docs/vendor/font-awesome/less/bordered-pulled.less: -------------------------------------------------------------------------------- 1 | // Bordered & Pulled 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix}-border { 5 | padding: .2em .25em .15em; 6 | border: solid .08em @fa-border-color; 7 | border-radius: .1em; 8 | } 9 | 10 | .@{fa-css-prefix}-pull-left { float: left; } 11 | .@{fa-css-prefix}-pull-right { float: right; } 12 | 13 | .@{fa-css-prefix} { 14 | &.@{fa-css-prefix}-pull-left { margin-right: .3em; } 15 | &.@{fa-css-prefix}-pull-right { margin-left: .3em; } 16 | } 17 | 18 | /* Deprecated as of 4.4.0 */ 19 | .pull-right { float: right; } 20 | .pull-left { float: left; } 21 | 22 | .@{fa-css-prefix} { 23 | &.pull-left { margin-right: .3em; } 24 | &.pull-right { margin-left: .3em; } 25 | } 26 | -------------------------------------------------------------------------------- /docs/vendor/font-awesome/less/core.less: -------------------------------------------------------------------------------- 1 | // Base Class Definition 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix} { 5 | display: inline-block; 6 | font: normal normal normal @fa-font-size-base/@fa-line-height-base FontAwesome; // shortening font declaration 7 | font-size: inherit; // can't have font-size inherit on line above, so need to override 8 | text-rendering: auto; // optimizelegibility throws things off #1094 9 | -webkit-font-smoothing: antialiased; 10 | -moz-osx-font-smoothing: grayscale; 11 | 12 | } 13 | -------------------------------------------------------------------------------- /docs/vendor/font-awesome/less/fixed-width.less: -------------------------------------------------------------------------------- 1 | // Fixed Width Icons 2 | // ------------------------- 3 | .@{fa-css-prefix}-fw { 4 | width: (18em / 14); 5 | text-align: center; 6 | } 7 | -------------------------------------------------------------------------------- /docs/vendor/font-awesome/less/font-awesome.less: -------------------------------------------------------------------------------- 1 | /*! 2 | * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome 3 | * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) 4 | */ 5 | 6 | @import "variables.less"; 7 | @import "mixins.less"; 8 | @import "path.less"; 9 | @import "core.less"; 10 | @import "larger.less"; 11 | @import "fixed-width.less"; 12 | @import "list.less"; 13 | @import "bordered-pulled.less"; 14 | @import "animated.less"; 15 | @import "rotated-flipped.less"; 16 | @import "stacked.less"; 17 | @import "icons.less"; 18 | @import "screen-reader.less"; 19 | -------------------------------------------------------------------------------- /docs/vendor/font-awesome/less/larger.less: -------------------------------------------------------------------------------- 1 | // Icon Sizes 2 | // ------------------------- 3 | 4 | /* makes the font 33% larger relative to the icon container */ 5 | .@{fa-css-prefix}-lg { 6 | font-size: (4em / 3); 7 | line-height: (3em / 4); 8 | vertical-align: -15%; 9 | } 10 | .@{fa-css-prefix}-2x { font-size: 2em; } 11 | .@{fa-css-prefix}-3x { font-size: 3em; } 12 | .@{fa-css-prefix}-4x { font-size: 4em; } 13 | .@{fa-css-prefix}-5x { font-size: 5em; } 14 | -------------------------------------------------------------------------------- /docs/vendor/font-awesome/less/list.less: -------------------------------------------------------------------------------- 1 | // List Icons 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix}-ul { 5 | padding-left: 0; 6 | margin-left: @fa-li-width; 7 | list-style-type: none; 8 | > li { position: relative; } 9 | } 10 | .@{fa-css-prefix}-li { 11 | position: absolute; 12 | left: -@fa-li-width; 13 | width: @fa-li-width; 14 | top: (2em / 14); 15 | text-align: center; 16 | &.@{fa-css-prefix}-lg { 17 | left: (-@fa-li-width + (4em / 14)); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /docs/vendor/font-awesome/less/mixins.less: -------------------------------------------------------------------------------- 1 | // Mixins 2 | // -------------------------- 3 | 4 | .fa-icon() { 5 | display: inline-block; 6 | font: normal normal normal @fa-font-size-base/@fa-line-height-base FontAwesome; // shortening font declaration 7 | font-size: inherit; // can't have font-size inherit on line above, so need to override 8 | text-rendering: auto; // optimizelegibility throws things off #1094 9 | -webkit-font-smoothing: antialiased; 10 | -moz-osx-font-smoothing: grayscale; 11 | 12 | } 13 | 14 | .fa-icon-rotate(@degrees, @rotation) { 15 | -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=@{rotation})"; 16 | -webkit-transform: rotate(@degrees); 17 | -ms-transform: rotate(@degrees); 18 | transform: rotate(@degrees); 19 | } 20 | 21 | .fa-icon-flip(@horiz, @vert, @rotation) { 22 | -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=@{rotation}, mirror=1)"; 23 | -webkit-transform: scale(@horiz, @vert); 24 | -ms-transform: scale(@horiz, @vert); 25 | transform: scale(@horiz, @vert); 26 | } 27 | 28 | 29 | // Only display content to screen readers. A la Bootstrap 4. 30 | // 31 | // See: http://a11yproject.com/posts/how-to-hide-content/ 32 | 33 | .sr-only() { 34 | position: absolute; 35 | width: 1px; 36 | height: 1px; 37 | padding: 0; 38 | margin: -1px; 39 | overflow: hidden; 40 | clip: rect(0,0,0,0); 41 | border: 0; 42 | } 43 | 44 | // Use in conjunction with .sr-only to only display content when it's focused. 45 | // 46 | // Useful for "Skip to main content" links; see http://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1 47 | // 48 | // Credit: HTML5 Boilerplate 49 | 50 | .sr-only-focusable() { 51 | &:active, 52 | &:focus { 53 | position: static; 54 | width: auto; 55 | height: auto; 56 | margin: 0; 57 | overflow: visible; 58 | clip: auto; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /docs/vendor/font-awesome/less/path.less: -------------------------------------------------------------------------------- 1 | /* FONT PATH 2 | * -------------------------- */ 3 | 4 | @font-face { 5 | font-family: 'FontAwesome'; 6 | src: url('@{fa-font-path}/fontawesome-webfont.eot?v=@{fa-version}'); 7 | src: url('@{fa-font-path}/fontawesome-webfont.eot?#iefix&v=@{fa-version}') format('embedded-opentype'), 8 | url('@{fa-font-path}/fontawesome-webfont.woff2?v=@{fa-version}') format('woff2'), 9 | url('@{fa-font-path}/fontawesome-webfont.woff?v=@{fa-version}') format('woff'), 10 | url('@{fa-font-path}/fontawesome-webfont.ttf?v=@{fa-version}') format('truetype'), 11 | url('@{fa-font-path}/fontawesome-webfont.svg?v=@{fa-version}#fontawesomeregular') format('svg'); 12 | // src: url('@{fa-font-path}/FontAwesome.otf') format('opentype'); // used when developing fonts 13 | font-weight: normal; 14 | font-style: normal; 15 | } 16 | -------------------------------------------------------------------------------- /docs/vendor/font-awesome/less/rotated-flipped.less: -------------------------------------------------------------------------------- 1 | // Rotated & Flipped Icons 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix}-rotate-90 { .fa-icon-rotate(90deg, 1); } 5 | .@{fa-css-prefix}-rotate-180 { .fa-icon-rotate(180deg, 2); } 6 | .@{fa-css-prefix}-rotate-270 { .fa-icon-rotate(270deg, 3); } 7 | 8 | .@{fa-css-prefix}-flip-horizontal { .fa-icon-flip(-1, 1, 0); } 9 | .@{fa-css-prefix}-flip-vertical { .fa-icon-flip(1, -1, 2); } 10 | 11 | // Hook for IE8-9 12 | // ------------------------- 13 | 14 | :root .@{fa-css-prefix}-rotate-90, 15 | :root .@{fa-css-prefix}-rotate-180, 16 | :root .@{fa-css-prefix}-rotate-270, 17 | :root .@{fa-css-prefix}-flip-horizontal, 18 | :root .@{fa-css-prefix}-flip-vertical { 19 | filter: none; 20 | } 21 | -------------------------------------------------------------------------------- /docs/vendor/font-awesome/less/screen-reader.less: -------------------------------------------------------------------------------- 1 | // Screen Readers 2 | // ------------------------- 3 | 4 | .sr-only { .sr-only(); } 5 | .sr-only-focusable { .sr-only-focusable(); } 6 | -------------------------------------------------------------------------------- /docs/vendor/font-awesome/less/stacked.less: -------------------------------------------------------------------------------- 1 | // Stacked Icons 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix}-stack { 5 | position: relative; 6 | display: inline-block; 7 | width: 2em; 8 | height: 2em; 9 | line-height: 2em; 10 | vertical-align: middle; 11 | } 12 | .@{fa-css-prefix}-stack-1x, .@{fa-css-prefix}-stack-2x { 13 | position: absolute; 14 | left: 0; 15 | width: 100%; 16 | text-align: center; 17 | } 18 | .@{fa-css-prefix}-stack-1x { line-height: inherit; } 19 | .@{fa-css-prefix}-stack-2x { font-size: 2em; } 20 | .@{fa-css-prefix}-inverse { color: @fa-inverse; } 21 | -------------------------------------------------------------------------------- /docs/vendor/font-awesome/scss/_animated.scss: -------------------------------------------------------------------------------- 1 | // Spinning Icons 2 | // -------------------------- 3 | 4 | .#{$fa-css-prefix}-spin { 5 | -webkit-animation: fa-spin 2s infinite linear; 6 | animation: fa-spin 2s infinite linear; 7 | } 8 | 9 | .#{$fa-css-prefix}-pulse { 10 | -webkit-animation: fa-spin 1s infinite steps(8); 11 | animation: fa-spin 1s infinite steps(8); 12 | } 13 | 14 | @-webkit-keyframes fa-spin { 15 | 0% { 16 | -webkit-transform: rotate(0deg); 17 | transform: rotate(0deg); 18 | } 19 | 100% { 20 | -webkit-transform: rotate(359deg); 21 | transform: rotate(359deg); 22 | } 23 | } 24 | 25 | @keyframes fa-spin { 26 | 0% { 27 | -webkit-transform: rotate(0deg); 28 | transform: rotate(0deg); 29 | } 30 | 100% { 31 | -webkit-transform: rotate(359deg); 32 | transform: rotate(359deg); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /docs/vendor/font-awesome/scss/_bordered-pulled.scss: -------------------------------------------------------------------------------- 1 | // Bordered & Pulled 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-border { 5 | padding: .2em .25em .15em; 6 | border: solid .08em $fa-border-color; 7 | border-radius: .1em; 8 | } 9 | 10 | .#{$fa-css-prefix}-pull-left { float: left; } 11 | .#{$fa-css-prefix}-pull-right { float: right; } 12 | 13 | .#{$fa-css-prefix} { 14 | &.#{$fa-css-prefix}-pull-left { margin-right: .3em; } 15 | &.#{$fa-css-prefix}-pull-right { margin-left: .3em; } 16 | } 17 | 18 | /* Deprecated as of 4.4.0 */ 19 | .pull-right { float: right; } 20 | .pull-left { float: left; } 21 | 22 | .#{$fa-css-prefix} { 23 | &.pull-left { margin-right: .3em; } 24 | &.pull-right { margin-left: .3em; } 25 | } 26 | -------------------------------------------------------------------------------- /docs/vendor/font-awesome/scss/_core.scss: -------------------------------------------------------------------------------- 1 | // Base Class Definition 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix} { 5 | display: inline-block; 6 | font: normal normal normal #{$fa-font-size-base}/#{$fa-line-height-base} FontAwesome; // shortening font declaration 7 | font-size: inherit; // can't have font-size inherit on line above, so need to override 8 | text-rendering: auto; // optimizelegibility throws things off #1094 9 | -webkit-font-smoothing: antialiased; 10 | -moz-osx-font-smoothing: grayscale; 11 | 12 | } 13 | -------------------------------------------------------------------------------- /docs/vendor/font-awesome/scss/_fixed-width.scss: -------------------------------------------------------------------------------- 1 | // Fixed Width Icons 2 | // ------------------------- 3 | .#{$fa-css-prefix}-fw { 4 | width: (18em / 14); 5 | text-align: center; 6 | } 7 | -------------------------------------------------------------------------------- /docs/vendor/font-awesome/scss/_larger.scss: -------------------------------------------------------------------------------- 1 | // Icon Sizes 2 | // ------------------------- 3 | 4 | /* makes the font 33% larger relative to the icon container */ 5 | .#{$fa-css-prefix}-lg { 6 | font-size: (4em / 3); 7 | line-height: (3em / 4); 8 | vertical-align: -15%; 9 | } 10 | .#{$fa-css-prefix}-2x { font-size: 2em; } 11 | .#{$fa-css-prefix}-3x { font-size: 3em; } 12 | .#{$fa-css-prefix}-4x { font-size: 4em; } 13 | .#{$fa-css-prefix}-5x { font-size: 5em; } 14 | -------------------------------------------------------------------------------- /docs/vendor/font-awesome/scss/_list.scss: -------------------------------------------------------------------------------- 1 | // List Icons 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-ul { 5 | padding-left: 0; 6 | margin-left: $fa-li-width; 7 | list-style-type: none; 8 | > li { position: relative; } 9 | } 10 | .#{$fa-css-prefix}-li { 11 | position: absolute; 12 | left: -$fa-li-width; 13 | width: $fa-li-width; 14 | top: (2em / 14); 15 | text-align: center; 16 | &.#{$fa-css-prefix}-lg { 17 | left: -$fa-li-width + (4em / 14); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /docs/vendor/font-awesome/scss/_mixins.scss: -------------------------------------------------------------------------------- 1 | // Mixins 2 | // -------------------------- 3 | 4 | @mixin fa-icon() { 5 | display: inline-block; 6 | font: normal normal normal #{$fa-font-size-base}/#{$fa-line-height-base} FontAwesome; // shortening font declaration 7 | font-size: inherit; // can't have font-size inherit on line above, so need to override 8 | text-rendering: auto; // optimizelegibility throws things off #1094 9 | -webkit-font-smoothing: antialiased; 10 | -moz-osx-font-smoothing: grayscale; 11 | 12 | } 13 | 14 | @mixin fa-icon-rotate($degrees, $rotation) { 15 | -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation})"; 16 | -webkit-transform: rotate($degrees); 17 | -ms-transform: rotate($degrees); 18 | transform: rotate($degrees); 19 | } 20 | 21 | @mixin fa-icon-flip($horiz, $vert, $rotation) { 22 | -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation}, mirror=1)"; 23 | -webkit-transform: scale($horiz, $vert); 24 | -ms-transform: scale($horiz, $vert); 25 | transform: scale($horiz, $vert); 26 | } 27 | 28 | 29 | // Only display content to screen readers. A la Bootstrap 4. 30 | // 31 | // See: http://a11yproject.com/posts/how-to-hide-content/ 32 | 33 | @mixin sr-only { 34 | position: absolute; 35 | width: 1px; 36 | height: 1px; 37 | padding: 0; 38 | margin: -1px; 39 | overflow: hidden; 40 | clip: rect(0,0,0,0); 41 | border: 0; 42 | } 43 | 44 | // Use in conjunction with .sr-only to only display content when it's focused. 45 | // 46 | // Useful for "Skip to main content" links; see http://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1 47 | // 48 | // Credit: HTML5 Boilerplate 49 | 50 | @mixin sr-only-focusable { 51 | &:active, 52 | &:focus { 53 | position: static; 54 | width: auto; 55 | height: auto; 56 | margin: 0; 57 | overflow: visible; 58 | clip: auto; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /docs/vendor/font-awesome/scss/_path.scss: -------------------------------------------------------------------------------- 1 | /* FONT PATH 2 | * -------------------------- */ 3 | 4 | @font-face { 5 | font-family: 'FontAwesome'; 6 | src: url('#{$fa-font-path}/fontawesome-webfont.eot?v=#{$fa-version}'); 7 | src: url('#{$fa-font-path}/fontawesome-webfont.eot?#iefix&v=#{$fa-version}') format('embedded-opentype'), 8 | url('#{$fa-font-path}/fontawesome-webfont.woff2?v=#{$fa-version}') format('woff2'), 9 | url('#{$fa-font-path}/fontawesome-webfont.woff?v=#{$fa-version}') format('woff'), 10 | url('#{$fa-font-path}/fontawesome-webfont.ttf?v=#{$fa-version}') format('truetype'), 11 | url('#{$fa-font-path}/fontawesome-webfont.svg?v=#{$fa-version}#fontawesomeregular') format('svg'); 12 | // src: url('#{$fa-font-path}/FontAwesome.otf') format('opentype'); // used when developing fonts 13 | font-weight: normal; 14 | font-style: normal; 15 | } 16 | -------------------------------------------------------------------------------- /docs/vendor/font-awesome/scss/_rotated-flipped.scss: -------------------------------------------------------------------------------- 1 | // Rotated & Flipped Icons 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-rotate-90 { @include fa-icon-rotate(90deg, 1); } 5 | .#{$fa-css-prefix}-rotate-180 { @include fa-icon-rotate(180deg, 2); } 6 | .#{$fa-css-prefix}-rotate-270 { @include fa-icon-rotate(270deg, 3); } 7 | 8 | .#{$fa-css-prefix}-flip-horizontal { @include fa-icon-flip(-1, 1, 0); } 9 | .#{$fa-css-prefix}-flip-vertical { @include fa-icon-flip(1, -1, 2); } 10 | 11 | // Hook for IE8-9 12 | // ------------------------- 13 | 14 | :root .#{$fa-css-prefix}-rotate-90, 15 | :root .#{$fa-css-prefix}-rotate-180, 16 | :root .#{$fa-css-prefix}-rotate-270, 17 | :root .#{$fa-css-prefix}-flip-horizontal, 18 | :root .#{$fa-css-prefix}-flip-vertical { 19 | filter: none; 20 | } 21 | -------------------------------------------------------------------------------- /docs/vendor/font-awesome/scss/_screen-reader.scss: -------------------------------------------------------------------------------- 1 | // Screen Readers 2 | // ------------------------- 3 | 4 | .sr-only { @include sr-only(); } 5 | .sr-only-focusable { @include sr-only-focusable(); } 6 | -------------------------------------------------------------------------------- /docs/vendor/font-awesome/scss/_stacked.scss: -------------------------------------------------------------------------------- 1 | // Stacked Icons 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-stack { 5 | position: relative; 6 | display: inline-block; 7 | width: 2em; 8 | height: 2em; 9 | line-height: 2em; 10 | vertical-align: middle; 11 | } 12 | .#{$fa-css-prefix}-stack-1x, .#{$fa-css-prefix}-stack-2x { 13 | position: absolute; 14 | left: 0; 15 | width: 100%; 16 | text-align: center; 17 | } 18 | .#{$fa-css-prefix}-stack-1x { line-height: inherit; } 19 | .#{$fa-css-prefix}-stack-2x { font-size: 2em; } 20 | .#{$fa-css-prefix}-inverse { color: $fa-inverse; } 21 | -------------------------------------------------------------------------------- /docs/vendor/font-awesome/scss/font-awesome.scss: -------------------------------------------------------------------------------- 1 | /*! 2 | * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome 3 | * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) 4 | */ 5 | 6 | @import "variables"; 7 | @import "mixins"; 8 | @import "path"; 9 | @import "core"; 10 | @import "larger"; 11 | @import "fixed-width"; 12 | @import "list"; 13 | @import "bordered-pulled"; 14 | @import "animated"; 15 | @import "rotated-flipped"; 16 | @import "stacked"; 17 | @import "icons"; 18 | @import "screen-reader"; 19 | -------------------------------------------------------------------------------- /docs/vendor/jquery-easing/jquery.easing.compatibility.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Easing Compatibility v1 - http://gsgd.co.uk/sandbox/jquery/easing 3 | * 4 | * Adds compatibility for applications that use the pre 1.2 easing names 5 | * 6 | * Copyright (c) 2007 George Smith 7 | * Licensed under the MIT License: 8 | * http://www.opensource.org/licenses/mit-license.php 9 | */ 10 | 11 | (function($){ 12 | $.extend( $.easing, 13 | { 14 | easeIn: function (x, t, b, c, d) { 15 | return $.easing.easeInQuad(x, t, b, c, d); 16 | }, 17 | easeOut: function (x, t, b, c, d) { 18 | return $.easing.easeOutQuad(x, t, b, c, d); 19 | }, 20 | easeInOut: function (x, t, b, c, d) { 21 | return $.easing.easeInOutQuad(x, t, b, c, d); 22 | }, 23 | expoin: function(x, t, b, c, d) { 24 | return $.easing.easeInExpo(x, t, b, c, d); 25 | }, 26 | expoout: function(x, t, b, c, d) { 27 | return $.easing.easeOutExpo(x, t, b, c, d); 28 | }, 29 | expoinout: function(x, t, b, c, d) { 30 | return $.easing.easeInOutExpo(x, t, b, c, d); 31 | }, 32 | bouncein: function(x, t, b, c, d) { 33 | return $.easing.easeInBounce(x, t, b, c, d); 34 | }, 35 | bounceout: function(x, t, b, c, d) { 36 | return $.easing.easeOutBounce(x, t, b, c, d); 37 | }, 38 | bounceinout: function(x, t, b, c, d) { 39 | return $.easing.easeInOutBounce(x, t, b, c, d); 40 | }, 41 | elasin: function(x, t, b, c, d) { 42 | return $.easing.easeInElastic(x, t, b, c, d); 43 | }, 44 | elasout: function(x, t, b, c, d) { 45 | return $.easing.easeOutElastic(x, t, b, c, d); 46 | }, 47 | elasinout: function(x, t, b, c, d) { 48 | return $.easing.easeInOutElastic(x, t, b, c, d); 49 | }, 50 | backin: function(x, t, b, c, d) { 51 | return $.easing.easeInBack(x, t, b, c, d); 52 | }, 53 | backout: function(x, t, b, c, d) { 54 | return $.easing.easeOutBack(x, t, b, c, d); 55 | }, 56 | backinout: function(x, t, b, c, d) { 57 | return $.easing.easeInOutBack(x, t, b, c, d); 58 | } 59 | });})(jQuery); 60 | -------------------------------------------------------------------------------- /docs/vendor/jquery-easing/jquery.easing.js: -------------------------------------------------------------------------------- 1 | /* 2 | * jQuery Easing v1.4.1 - http://gsgd.co.uk/sandbox/jquery/easing/ 3 | * Open source under the BSD License. 4 | * Copyright © 2008 George McGinley Smith 5 | * All rights reserved. 6 | * https://raw.github.com/gdsmith/jquery-easing/master/LICENSE 7 | */ 8 | 9 | (function (factory) { 10 | if (typeof define === "function" && define.amd) { 11 | define(['jquery'], function ($) { 12 | return factory($); 13 | }); 14 | } else if (typeof module === "object" && typeof module.exports === "object") { 15 | exports = factory(require('jquery')); 16 | } else { 17 | factory(jQuery); 18 | } 19 | })(function($){ 20 | 21 | // Preserve the original jQuery "swing" easing as "jswing" 22 | $.easing.jswing = $.easing.swing; 23 | 24 | var pow = Math.pow, 25 | sqrt = Math.sqrt, 26 | sin = Math.sin, 27 | cos = Math.cos, 28 | PI = Math.PI, 29 | c1 = 1.70158, 30 | c2 = c1 * 1.525, 31 | c3 = c1 + 1, 32 | c4 = ( 2 * PI ) / 3, 33 | c5 = ( 2 * PI ) / 4.5; 34 | 35 | // x is the fraction of animation progress, in the range 0..1 36 | function bounceOut(x) { 37 | var n1 = 7.5625, 38 | d1 = 2.75; 39 | if ( x < 1/d1 ) { 40 | return n1*x*x; 41 | } else if ( x < 2/d1 ) { 42 | return n1*(x-=(1.5/d1))*x + 0.75; 43 | } else if ( x < 2.5/d1 ) { 44 | return n1*(x-=(2.25/d1))*x + 0.9375; 45 | } else { 46 | return n1*(x-=(2.625/d1))*x + 0.984375; 47 | } 48 | } 49 | 50 | $.extend( $.easing, 51 | { 52 | def: 'easeOutQuad', 53 | swing: function (x) { 54 | return $.easing[$.easing.def](x); 55 | }, 56 | easeInQuad: function (x) { 57 | return x * x; 58 | }, 59 | easeOutQuad: function (x) { 60 | return 1 - ( 1 - x ) * ( 1 - x ); 61 | }, 62 | easeInOutQuad: function (x) { 63 | return x < 0.5 ? 64 | 2 * x * x : 65 | 1 - pow( -2 * x + 2, 2 ) / 2; 66 | }, 67 | easeInCubic: function (x) { 68 | return x * x * x; 69 | }, 70 | easeOutCubic: function (x) { 71 | return 1 - pow( 1 - x, 3 ); 72 | }, 73 | easeInOutCubic: function (x) { 74 | return x < 0.5 ? 75 | 4 * x * x * x : 76 | 1 - pow( -2 * x + 2, 3 ) / 2; 77 | }, 78 | easeInQuart: function (x) { 79 | return x * x * x * x; 80 | }, 81 | easeOutQuart: function (x) { 82 | return 1 - pow( 1 - x, 4 ); 83 | }, 84 | easeInOutQuart: function (x) { 85 | return x < 0.5 ? 86 | 8 * x * x * x * x : 87 | 1 - pow( -2 * x + 2, 4 ) / 2; 88 | }, 89 | easeInQuint: function (x) { 90 | return x * x * x * x * x; 91 | }, 92 | easeOutQuint: function (x) { 93 | return 1 - pow( 1 - x, 5 ); 94 | }, 95 | easeInOutQuint: function (x) { 96 | return x < 0.5 ? 97 | 16 * x * x * x * x * x : 98 | 1 - pow( -2 * x + 2, 5 ) / 2; 99 | }, 100 | easeInSine: function (x) { 101 | return 1 - cos( x * PI/2 ); 102 | }, 103 | easeOutSine: function (x) { 104 | return sin( x * PI/2 ); 105 | }, 106 | easeInOutSine: function (x) { 107 | return -( cos( PI * x ) - 1 ) / 2; 108 | }, 109 | easeInExpo: function (x) { 110 | return x === 0 ? 0 : pow( 2, 10 * x - 10 ); 111 | }, 112 | easeOutExpo: function (x) { 113 | return x === 1 ? 1 : 1 - pow( 2, -10 * x ); 114 | }, 115 | easeInOutExpo: function (x) { 116 | return x === 0 ? 0 : x === 1 ? 1 : x < 0.5 ? 117 | pow( 2, 20 * x - 10 ) / 2 : 118 | ( 2 - pow( 2, -20 * x + 10 ) ) / 2; 119 | }, 120 | easeInCirc: function (x) { 121 | return 1 - sqrt( 1 - pow( x, 2 ) ); 122 | }, 123 | easeOutCirc: function (x) { 124 | return sqrt( 1 - pow( x - 1, 2 ) ); 125 | }, 126 | easeInOutCirc: function (x) { 127 | return x < 0.5 ? 128 | ( 1 - sqrt( 1 - pow( 2 * x, 2 ) ) ) / 2 : 129 | ( sqrt( 1 - pow( -2 * x + 2, 2 ) ) + 1 ) / 2; 130 | }, 131 | easeInElastic: function (x) { 132 | return x === 0 ? 0 : x === 1 ? 1 : 133 | -pow( 2, 10 * x - 10 ) * sin( ( x * 10 - 10.75 ) * c4 ); 134 | }, 135 | easeOutElastic: function (x) { 136 | return x === 0 ? 0 : x === 1 ? 1 : 137 | pow( 2, -10 * x ) * sin( ( x * 10 - 0.75 ) * c4 ) + 1; 138 | }, 139 | easeInOutElastic: function (x) { 140 | return x === 0 ? 0 : x === 1 ? 1 : x < 0.5 ? 141 | -( pow( 2, 20 * x - 10 ) * sin( ( 20 * x - 11.125 ) * c5 )) / 2 : 142 | pow( 2, -20 * x + 10 ) * sin( ( 20 * x - 11.125 ) * c5 ) / 2 + 1; 143 | }, 144 | easeInBack: function (x) { 145 | return c3 * x * x * x - c1 * x * x; 146 | }, 147 | easeOutBack: function (x) { 148 | return 1 + c3 * pow( x - 1, 3 ) + c1 * pow( x - 1, 2 ); 149 | }, 150 | easeInOutBack: function (x) { 151 | return x < 0.5 ? 152 | ( pow( 2 * x, 2 ) * ( ( c2 + 1 ) * 2 * x - c2 ) ) / 2 : 153 | ( pow( 2 * x - 2, 2 ) *( ( c2 + 1 ) * ( x * 2 - 2 ) + c2 ) + 2 ) / 2; 154 | }, 155 | easeInBounce: function (x) { 156 | return 1 - bounceOut( 1 - x ); 157 | }, 158 | easeOutBounce: bounceOut, 159 | easeInOutBounce: function (x) { 160 | return x < 0.5 ? 161 | ( 1 - bounceOut( 1 - 2 * x ) ) / 2 : 162 | ( 1 + bounceOut( 2 * x - 1 ) ) / 2; 163 | } 164 | }); 165 | 166 | }); 167 | -------------------------------------------------------------------------------- /docs/vendor/jquery-easing/jquery.easing.min.js: -------------------------------------------------------------------------------- 1 | (function(factory){if(typeof define==="function"&&define.amd){define(["jquery"],function($){return factory($)})}else if(typeof module==="object"&&typeof module.exports==="object"){exports=factory(require("jquery"))}else{factory(jQuery)}})(function($){$.easing.jswing=$.easing.swing;var pow=Math.pow,sqrt=Math.sqrt,sin=Math.sin,cos=Math.cos,PI=Math.PI,c1=1.70158,c2=c1*1.525,c3=c1+1,c4=2*PI/3,c5=2*PI/4.5;function bounceOut(x){var n1=7.5625,d1=2.75;if(x<1/d1){return n1*x*x}else if(x<2/d1){return n1*(x-=1.5/d1)*x+.75}else if(x<2.5/d1){return n1*(x-=2.25/d1)*x+.9375}else{return n1*(x-=2.625/d1)*x+.984375}}$.extend($.easing,{def:"easeOutQuad",swing:function(x){return $.easing[$.easing.def](x)},easeInQuad:function(x){return x*x},easeOutQuad:function(x){return 1-(1-x)*(1-x)},easeInOutQuad:function(x){return x<.5?2*x*x:1-pow(-2*x+2,2)/2},easeInCubic:function(x){return x*x*x},easeOutCubic:function(x){return 1-pow(1-x,3)},easeInOutCubic:function(x){return x<.5?4*x*x*x:1-pow(-2*x+2,3)/2},easeInQuart:function(x){return x*x*x*x},easeOutQuart:function(x){return 1-pow(1-x,4)},easeInOutQuart:function(x){return x<.5?8*x*x*x*x:1-pow(-2*x+2,4)/2},easeInQuint:function(x){return x*x*x*x*x},easeOutQuint:function(x){return 1-pow(1-x,5)},easeInOutQuint:function(x){return x<.5?16*x*x*x*x*x:1-pow(-2*x+2,5)/2},easeInSine:function(x){return 1-cos(x*PI/2)},easeOutSine:function(x){return sin(x*PI/2)},easeInOutSine:function(x){return-(cos(PI*x)-1)/2},easeInExpo:function(x){return x===0?0:pow(2,10*x-10)},easeOutExpo:function(x){return x===1?1:1-pow(2,-10*x)},easeInOutExpo:function(x){return x===0?0:x===1?1:x<.5?pow(2,20*x-10)/2:(2-pow(2,-20*x+10))/2},easeInCirc:function(x){return 1-sqrt(1-pow(x,2))},easeOutCirc:function(x){return sqrt(1-pow(x-1,2))},easeInOutCirc:function(x){return x<.5?(1-sqrt(1-pow(2*x,2)))/2:(sqrt(1-pow(-2*x+2,2))+1)/2},easeInElastic:function(x){return x===0?0:x===1?1:-pow(2,10*x-10)*sin((x*10-10.75)*c4)},easeOutElastic:function(x){return x===0?0:x===1?1:pow(2,-10*x)*sin((x*10-.75)*c4)+1},easeInOutElastic:function(x){return x===0?0:x===1?1:x<.5?-(pow(2,20*x-10)*sin((20*x-11.125)*c5))/2:pow(2,-20*x+10)*sin((20*x-11.125)*c5)/2+1},easeInBack:function(x){return c3*x*x*x-c1*x*x},easeOutBack:function(x){return 1+c3*pow(x-1,3)+c1*pow(x-1,2)},easeInOutBack:function(x){return x<.5?pow(2*x,2)*((c2+1)*2*x-c2)/2:(pow(2*x-2,2)*((c2+1)*(x*2-2)+c2)+2)/2},easeInBounce:function(x){return 1-bounceOut(1-x)},easeOutBounce:bounceOut,easeInOutBounce:function(x){return x<.5?(1-bounceOut(1-2*x))/2:(1+bounceOut(2*x-1))/2}})}); -------------------------------------------------------------------------------- /docs/vendor/simple-line-icons/fonts/Simple-Line-Icons.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick92/coffee/2bae1178be34bbf72a92143a4534ac2e739b4a8d/docs/vendor/simple-line-icons/fonts/Simple-Line-Icons.eot -------------------------------------------------------------------------------- /docs/vendor/simple-line-icons/fonts/Simple-Line-Icons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick92/coffee/2bae1178be34bbf72a92143a4534ac2e739b4a8d/docs/vendor/simple-line-icons/fonts/Simple-Line-Icons.ttf -------------------------------------------------------------------------------- /docs/vendor/simple-line-icons/fonts/Simple-Line-Icons.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick92/coffee/2bae1178be34bbf72a92143a4534ac2e739b4a8d/docs/vendor/simple-line-icons/fonts/Simple-Line-Icons.woff -------------------------------------------------------------------------------- /docs/vendor/simple-line-icons/fonts/Simple-Line-Icons.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nick92/coffee/2bae1178be34bbf72a92143a4534ac2e739b4a8d/docs/vendor/simple-line-icons/fonts/Simple-Line-Icons.woff2 -------------------------------------------------------------------------------- /meson.build: -------------------------------------------------------------------------------- 1 | project ('com.github.nick92.coffee', ['vala', 'c']) 2 | 3 | gettext_name = meson.project_name() 4 | 5 | add_project_arguments(['--vapidir', join_paths(meson.current_source_dir(), 'vapi')], language: 'vala') 6 | 7 | add_project_arguments( 8 | '-DGETTEXT_PACKAGE="@0@"'.format(gettext_name), 9 | '-DI_KNOW_THE_PACKAGEKIT_GLIB2_API_IS_SUBJECT_TO_CHANGE', 10 | language:'c' 11 | ) 12 | 13 | glib = dependency ('glib-2.0') 14 | gtk = dependency ('gtk+-3.0') 15 | json = dependency ('json-glib-1.0') 16 | soup = dependency ('libsoup-2.4') 17 | gee = dependency ('gee-0.8') 18 | geocode = dependency('geocode-glib-1.0') 19 | geoclue = dependency('libgeoclue-2.0') 20 | 21 | conf_data = configuration_data() 22 | 23 | subdir ('data') 24 | subdir ('src') -------------------------------------------------------------------------------- /meson/post_install.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import os 4 | import subprocess 5 | 6 | schemadir = os.path.join(os.environ['MESON_INSTALL_PREFIX'], 'share', 'glib-2.0', 'schemas') 7 | 8 | if not os.environ.get('DESTDIR'): 9 | print('Compiling gsettings schemas...') 10 | subprocess.call(['glib-compile-schemas', schemadir]) -------------------------------------------------------------------------------- /snap/.snapcraft/state: -------------------------------------------------------------------------------- 1 | !GlobalState 2 | assets: 3 | build-packages: [libjavascriptcoregtk-4.0-dev=2.24.1-0ubuntu0.18.04.1, libwebkit2gtk-4.0-dev=2.24.1-0ubuntu0.18.04.1] 4 | build-snaps: [] 5 | -------------------------------------------------------------------------------- /snap/snapcraft.yaml: -------------------------------------------------------------------------------- 1 | name: coffee-news # you probably want to 'snapcraft register ' 2 | version: '2.2.0' # just for humans, typically '1.2+git' or '1.3.2' 3 | summary: Keep up-to-date with news and weather with Coffee # 79 char long summary 4 | description: | 5 | Get the latest news and weather information with Coffee, keep up-to-date with the local weather information and news from a variety of sources 6 | 7 | grade: stable # must be 'stable' to release into candidate/stable channels 8 | confinement: strict # use 'strict' once you have the right plugs and slots 9 | 10 | apps: 11 | coffee: 12 | command: com.github.nick92.coffee 13 | environment: 14 | GSETTINGS_SCHEMA_DIR: $SNAP/share/glib-2.0/schemas 15 | 16 | parts: 17 | coffee: 18 | source: https://github.com/nick92/coffee.git 19 | plugin: meson 20 | source-type: git 21 | build-packages: 22 | - libgtk-3-dev 23 | - valac 24 | - libglib2.0-dev 25 | - libjson-glib-dev 26 | - libsoup2.4-dev 27 | - libgee-0.8-dev 28 | - libgeocode-glib-dev 29 | - libgeoclue-2-dev -------------------------------------------------------------------------------- /src/Main.vala: -------------------------------------------------------------------------------- 1 | /* 2 | * Main.vala 3 | * This file is part of Coffee 4 | * 5 | * Copyright (C) 2017 - Nick Wilkins 6 | * 7 | * Coffee is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * Coffee is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with Coffee. If not, see . 19 | */ 20 | using Gtk; 21 | 22 | namespace Coffee { 23 | 24 | public class CoffeeApp : Gtk.Application { 25 | 26 | CoffeeBar bar = null; 27 | static CoffeeApp? app = null; 28 | const string ACTIVTE_KEY = "F10"; 29 | const string QUIT_KEY = "F4"; 30 | static bool debug = false; 31 | static bool version = false; 32 | 33 | const OptionEntry[] options = { 34 | { "debug", 'd', 0, OptionArg.NONE, ref debug, "Enable debug logging", null }, 35 | { "version", 'v', 0, OptionArg.NONE, ref version, "Show the application's version", null }, 36 | { null } 37 | }; 38 | 39 | protected override void activate () { 40 | var provider = new Gtk.CssProvider (); 41 | provider.load_from_resource ("com/github/nick92/Coffee/application.css"); 42 | Gtk.StyleContext.add_provider_for_screen (Gdk.Screen.get_default (), provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); 43 | 44 | if (this.get_windows () == null) { 45 | bar = new CoffeeBar (this); 46 | } 47 | } 48 | 49 | public CoffeeApp () { 50 | 51 | } 52 | 53 | public static int main(string[] args) { 54 | Gtk.init (ref args); 55 | 56 | Plank.Logger.initialize ("coffee"); 57 | 58 | if (args.length > 1) { 59 | var context = new OptionContext (""); 60 | context.add_main_entries (options, "coffee"); 61 | context.add_group (Gtk.get_option_group (true)); 62 | 63 | try { 64 | context.parse (ref args); 65 | } catch (Error e) { 66 | print (e.message + "\n"); 67 | } 68 | } 69 | 70 | if (version) 71 | Plank.Logger.DisplayLevel = Plank.LogLevel.VERBOSE; 72 | else if (debug) 73 | Plank.Logger.DisplayLevel = Plank.LogLevel.DEBUG; 74 | 75 | app = new CoffeeApp (); 76 | return app.run (args); 77 | } 78 | 79 | public string load_from_resource (string uri) throws IOError, Error { 80 | var stream = resources_open_stream (uri, ResourceLookupFlags.NONE); 81 | var dis = new DataInputStream(stream); 82 | StringBuilder builder = new StringBuilder (); 83 | string line; 84 | while ( (line = dis.read_line (null)) != null ) { 85 | builder.append (line); 86 | } 87 | return builder.str.dup (); 88 | } 89 | 90 | public string load_css_from_resource (string uri, string append) throws IOError, Error { 91 | var stream = resources_open_stream (uri, ResourceLookupFlags.NONE); 92 | var dis = new DataInputStream(stream); 93 | StringBuilder builder = new StringBuilder (); 94 | string line; 95 | while ( (line = dis.read_line (null)) != null ) { 96 | builder.append (line); 97 | } 98 | if(append != "") 99 | builder.append (append); 100 | 101 | return builder.str.dup (); 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/Post.vala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017 - Nick Wilkins 3 | * 4 | * Coffee is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Coffee is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with Coffee. If not, see . 16 | */ 17 | using Gtk; 18 | 19 | namespace Coffee { 20 | public class Post : Object { 21 | 22 | private Gee.ArrayList posts = null; 23 | 24 | static Post? instance = null; 25 | 26 | public string title { get; set; } 27 | public string image_link { get; set; } 28 | public string subject { get; set; } 29 | public string author { get; set; } 30 | public string link { get; set; } 31 | 32 | public signal void post_added (); 33 | public signal void post_add_completed (); 34 | 35 | public Post () { 36 | posts = new Gee.ArrayList(); 37 | } 38 | 39 | public static Post get_default () { 40 | if (instance == null) { 41 | instance = new Post (); 42 | } 43 | 44 | return instance; 45 | } 46 | 47 | public void add_post (Post post) 48 | { 49 | posts.add(post); 50 | post_added (); 51 | } 52 | 53 | public void clear_posts () 54 | { 55 | posts.clear(); 56 | } 57 | 58 | public void parse_completed () 59 | { 60 | post_add_completed(); 61 | } 62 | 63 | public Gee.ArrayList get_posts () { 64 | if(posts == null){ 65 | return new Gee.ArrayList(); 66 | } 67 | 68 | return posts; 69 | } 70 | 71 | public int get_count () { 72 | return posts.size; 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/Settings/General/AboutGrid.vala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017 - Nick Wilkins 3 | * 4 | * Coffee is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Coffee is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with Coffee. If not, see . 16 | */ 17 | using Gtk; 18 | 19 | namespace Settings { 20 | public class General.AboutGrid : Grid { 21 | 22 | private Gtk.Switch _switch_weather; 23 | private Gtk.Switch _switch_news; 24 | 25 | private Gtk.Button hide_show_key; 26 | private Gtk.Button close_key; 27 | private Gtk.Button btn_donate; 28 | private Settings settings; 29 | 30 | public AboutGrid () { 31 | column_spacing = 12; 32 | halign = Gtk.Align.CENTER; 33 | row_spacing = 6; 34 | margin_start = margin_end = 6; 35 | 36 | settings = Settings.get_default (); 37 | 38 | var hide_show_label = new Gtk.Label("Hide / Show Coffee:"); 39 | hide_show_label.halign = Gtk.Align.END; 40 | 41 | var close_label = new Gtk.Label("Quit Coffee:"); 42 | close_label.halign = Gtk.Align.END; 43 | 44 | var donate_label = new Gtk.Label("Help Coffee:"); 45 | donate_label.halign = Gtk.Align.END; 46 | 47 | hide_show_key = new Gtk.Button.with_label("F10"); 48 | hide_show_key.sensitive = false; 49 | hide_show_key.halign = Gtk.Align.END; 50 | 51 | close_key = new Gtk.Button.with_label("Esc / F4"); 52 | close_key.sensitive = false; 53 | close_key.halign = Gtk.Align.END; 54 | 55 | btn_donate = new Gtk.Button.with_label("Donate"); 56 | btn_donate.halign = Gtk.Align.END; 57 | 58 | var weather_label = new Gtk.Label("Weather:"); 59 | weather_label.halign = Gtk.Align.END; 60 | _switch_weather = new Gtk.Switch (); 61 | 62 | var news_label = new Gtk.Label("News:"); 63 | news_label.halign = Gtk.Align.END; 64 | _switch_news = new Gtk.Switch (); 65 | 66 | if(settings.news_bool) 67 | _switch_news.active = true; 68 | 69 | if(settings.weather_bool) 70 | _switch_weather.active = true; 71 | 72 | //attach(weather_label, 1, 0, 1, 1); 73 | //attach(_switch_weather, 2, 0, 1, 1); 74 | //attach(news_label, 1, 1, 1, 1); 75 | //attach(_switch_news, 2, 1, 1, 1); 76 | attach(hide_show_label, 1, 2, 1, 1); 77 | attach(hide_show_key, 2, 2, 1, 1); 78 | attach(close_label, 1, 3, 1, 1); 79 | attach(close_key, 2, 3, 1, 1); 80 | attach(donate_label, 1, 4, 1, 1); 81 | attach(btn_donate, 2, 4, 1, 1); 82 | 83 | _switch_weather.notify["active"].connect (() => { 84 | settings.change_setting_bool(_switch_weather.active, settings.weather_string); 85 | }); 86 | _switch_news.notify["active"].connect (() => { 87 | settings.change_setting_bool(_switch_news.active, settings.news_string); 88 | }); 89 | 90 | connect_events (); 91 | } 92 | 93 | private void connect_events () { 94 | hide_show_key.clicked.connect (() => { 95 | hide_show_key.set_label ("Assign New Key ..."); 96 | hide_show_key.key_press_event.connect (key_press_event); 97 | }); 98 | 99 | btn_donate.clicked.connect (() => { 100 | var stripe_dialog = new StripeDialog(20, "Coffee", "", "pk_test_KLh0MCbZmwQHPtbEyGlQvR9Q"); 101 | stripe_dialog.show_all(); 102 | }); 103 | } 104 | 105 | private bool key_press_event (Gdk.EventKey event){ 106 | hide_show_key.set_label (event.keyval.to_string ()); 107 | hide_show_key.key_press_event.disconnect (key_press_event); 108 | return true; 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/Settings/News/Dialog/NewsListRow.vala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 - Nick Wilkins 3 | * 4 | * Coffee is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Coffee is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with Coffee. If not, see . 16 | */ 17 | using Gtk; 18 | 19 | namespace Settings { 20 | public class News.NewsListRow : Gtk.ListBoxRow { 21 | public NewsSource news_source { get; construct; } 22 | private Gtk.Grid info_grid; 23 | private Gtk.Image image; 24 | private Gtk.Label package_name; 25 | private Gtk.Label package_info; 26 | private NewsSourceGet get_news_source; 27 | public Gtk.CheckButton checkbox; 28 | 29 | public NewsListRow (NewsSource news_source) { 30 | Object (news_source : news_source); 31 | } 32 | 33 | construct { 34 | //margin = 6; 35 | margin_start = 12; 36 | margin_end = 12; 37 | 38 | image = new Gtk.Image (); 39 | checkbox = new Gtk.CheckButton (); 40 | package_name = new Gtk.Label (news_source.name ?? ""); 41 | package_info = new Gtk.Label (news_source.description ?? ""); 42 | //get_news_source = new NewsSourceGet (); 43 | 44 | image.icon_size = Gtk.IconSize.DIALOG; 45 | /* Needed to enforce size on icons from Filesystem/Remote */ 46 | image.pixel_size = 68; 47 | 48 | package_name.get_style_context ().add_class ("h1"); 49 | package_name.valign = Gtk.Align.CENTER; 50 | package_name.halign = Gtk.Align.START; 51 | package_name.margin = 5; 52 | 53 | package_info.get_style_context ().add_class ("h3"); 54 | package_info.valign = Gtk.Align.CENTER; 55 | package_info.halign = Gtk.Align.START; 56 | package_info.margin = 5; 57 | package_info.set_line_wrap (true); 58 | package_info.lines = 2; 59 | package_info.set_single_line_mode (false); 60 | package_info.wrap_mode = Pango.WrapMode.WORD_CHAR; 61 | package_info.set_ellipsize (Pango.EllipsizeMode.END); 62 | 63 | info_grid = new Gtk.Grid (); 64 | info_grid.column_spacing = 12; 65 | info_grid.row_spacing = 6; 66 | info_grid.valign = Gtk.Align.START; 67 | //info_grid.attach (image, 0, 0, 1, 2); 68 | info_grid.attach (checkbox, 0, 0, 1, 1); 69 | info_grid.attach (package_name, 1, 0, 1, 1); 70 | info_grid.attach (package_info, 1, 1, 1, 1); 71 | 72 | //action_stack.margin_top = 10; 73 | //action_stack.valign = Gtk.Align.START; 74 | 75 | add (info_grid); 76 | //add (action_stack, 3, 0, 1, 1); 77 | //child = info_grid; 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/Settings/News/Dialog/NewsSourcesGet.vala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 - Nick Wilkins 3 | * 4 | * Coffee is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Coffee is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with Coffee. If not, see . 16 | */ 17 | using Gtk; 18 | 19 | namespace Settings { 20 | public class News.NewsSourceGet : Object { 21 | 22 | private string sources_uri = "https://newsapi.org/v2/sources?"; 23 | //private string sources_uri = "https://newsapi.org/v2/sources?apiKey=e8a66b24da89420b9a419849e95d47a1"; 24 | private string besticons_uri = "https://coffee-favicon.herokuapp.com/allicons.json?url="; 25 | //https://besticon.herokuapp.com/allicons.json?url= 26 | private NewsSource news_sources; 27 | private string apiKey = "e8a66b24da89420b9a419849e95d47a1"; 28 | 29 | construct { 30 | news_sources = NewsSource.get_default (); 31 | } 32 | 33 | public void get_sources (string category = "", string country = "") { 34 | if(category != "" && country != "") 35 | sources_uri = "https://newsapi.org/v2/sources?" + "category=" + category + "&language=" + country + "&apiKey=" + apiKey; 36 | else 37 | sources_uri = "https://newsapi.org/v2/sources?" + "apiKey=" + apiKey; 38 | 39 | var session = new Soup.Session (); 40 | var message = new Soup.Message ("GET", sources_uri); 41 | session.send_message (message); 42 | parse_message(message); 43 | } 44 | 45 | private void parse_message (Soup.Message message){ 46 | try { 47 | var parser = new Json.Parser (); 48 | parser.load_from_data ((string) message.response_body.flatten ().data, -1); 49 | var root_object = parser.get_root ().get_object(); 50 | if(root_object.get_array_member ("sources") != null) { 51 | var response = root_object.get_array_member ("sources"); 52 | add_sources(response); 53 | } 54 | } catch (Error e) { 55 | stderr.printf ("I guess something is not working...\n"+e.message); 56 | } 57 | } 58 | 59 | private Json.Object process_response (string res) throws Error { 60 | var parser = new Json.Parser (); 61 | parser.load_from_data (res, -1); 62 | 63 | var root = parser.get_root ().get_object (); 64 | 65 | if (root.has_member ("errors") && root.get_array_member ("errors").get_length () > 0) { 66 | var err = root.get_array_member ("errors").get_object_element (0).get_string_member ("title"); 67 | 68 | if (err != null) { 69 | throw new Error (0, 0, err); 70 | } else { 71 | throw new Error (0, 0, "Error while talking to Houston"); 72 | } 73 | } 74 | 75 | return root; 76 | } 77 | 78 | public async string get_besticon_url (string source_name){ 79 | debug("get_besticon_url("+source_name+")"); 80 | var uri = besticons_uri + source_name; 81 | var session = new Soup.Session (); 82 | string besticon_url = ""; 83 | var message = new Soup.Message ("GET", uri); 84 | session.queue_message (message, (sess, mess) => { 85 | try { 86 | besticon_url = parse_besticon_message (mess); 87 | } catch (Error e) { 88 | warning ("Besticon: %s", e.message); 89 | } 90 | Idle.add (get_besticon_url.callback); 91 | }); 92 | 93 | yield; 94 | return besticon_url; 95 | } 96 | 97 | private string parse_besticon_message (Soup.Message message){ 98 | try { 99 | var parser = new Json.Parser (); 100 | parser.load_from_data ((string) message.response_body.flatten ().data, -1); 101 | var root_object = parser.get_root ().get_object(); 102 | if(root_object.get_array_member ("icons") != null && root_object.get_array_member ("icons").get_length() > 0) { 103 | var response = root_object.get_array_member ("icons").get_object_element(1);; 104 | //warning(response.get_string_member ("url")); 105 | //if(response.get_string_member ("format") == "ico") 106 | // response = root_object.get_array_member ("icons").get_object_element(1); 107 | return response.get_string_member ("url"); 108 | } 109 | else 110 | return ""; 111 | } catch (Error e) { 112 | stderr.printf ("I guess something is not working...\n"+e.message); 113 | return ""; 114 | } 115 | } 116 | 117 | private async void add_sources (Json.Array response){ 118 | int i = 0; 119 | 120 | foreach (var geonode in response.get_elements ()) { 121 | var geoname = geonode.get_object (); 122 | var news_source = new NewsSource (); 123 | news_source.id = geoname.get_string_member ("id"); 124 | news_source.name = geoname.get_string_member ("name"); 125 | news_source.description = geoname.get_string_member ("description"); 126 | news_source.url = geoname.get_string_member ("url"); 127 | news_source.category = geoname.get_string_member ("category"); 128 | news_source.country = geoname.get_string_member ("country"); 129 | 130 | //get_besticon_url.begin (news_source.url, (obj, res) => { 131 | //news_source.besticon_url = yield get_besticon_url (geoname.get_string_member ("url")); 132 | //}); 133 | //warning (news_source.besticon_url); 134 | news_sources.add_source (news_source); 135 | i++; 136 | } 137 | news_sources.get_sources_completed (); 138 | } 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /src/Settings/News/Dialog/Sidebar.vala: -------------------------------------------------------------------------------- 1 | // -*- Mode: vala; indent-tabs-mode: nil; tab-width: 4 -*- 2 | // 3 | // Copyright (C) 2011-2012 Giulio Collura 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | // 18 | 19 | using Gtk; 20 | 21 | public class Settings.News.Sidebar : Gtk.TreeView { 22 | 23 | private Gtk.TreeStore store; 24 | private Gtk.TreeIter entry_iter; 25 | 26 | public int cat_size { 27 | get { 28 | return store.iter_n_children (null); 29 | } 30 | } 31 | 32 | private int _selected = 0; 33 | public int selected { 34 | get { 35 | return _selected; 36 | } 37 | set { 38 | if (value >= 0 && value < cat_size) { 39 | select_nth (value); 40 | _selected = value; 41 | } 42 | } 43 | } 44 | 45 | private enum Columns { 46 | INT, 47 | TEXT, 48 | N_COLUMNS 49 | } 50 | 51 | public signal void selection_changed (string entry_name, int nth); 52 | 53 | public Sidebar () { 54 | 55 | store = new Gtk.TreeStore (Columns.N_COLUMNS, typeof (int), typeof (string)); 56 | //store.set_sort_column_id (1, Gtk.SortType.ASCENDING); 57 | set_model (store); 58 | 59 | set_headers_visible (false); 60 | set_show_expanders (false); 61 | //set_level_indentation (8); 62 | 63 | hexpand = false; 64 | get_style_context ().add_class ("sidebar"); 65 | 66 | var cell = new Gtk.CellRendererText (); 67 | cell.xpad = 10; 68 | cell.ypad = 5; 69 | 70 | insert_column_with_attributes (-1, "Filters", cell, "markup", Columns.TEXT); 71 | 72 | get_selection ().set_mode (Gtk.SelectionMode.SINGLE); 73 | get_selection ().changed.connect (selection_change); 74 | 75 | } 76 | 77 | public void add_category (string entry_name) { 78 | store.append (out entry_iter, null); 79 | store.set (entry_iter, Columns.INT, cat_size - 1, Columns.TEXT, Markup.escape_text (entry_name), -1); 80 | expand_all (); 81 | } 82 | 83 | public void clear () { 84 | store.clear (); 85 | } 86 | 87 | public void selection_change () { 88 | 89 | Gtk.TreeModel model; 90 | Gtk.TreeIter sel_iter; 91 | string name; 92 | int nth; 93 | 94 | if (get_selection ().get_selected (out model, out sel_iter)) { 95 | store.get (sel_iter, Columns.INT, out nth, Columns.TEXT, out name); 96 | _selected = nth; 97 | selection_changed (name, nth); 98 | } 99 | 100 | } 101 | 102 | public bool select_nth (int nth) { 103 | 104 | Gtk.TreeIter iter; 105 | 106 | if (nth < cat_size) 107 | store.iter_nth_child (out iter, null, nth); 108 | else 109 | return false; 110 | 111 | get_selection ().select_iter (iter); 112 | return true; 113 | 114 | } 115 | 116 | protected override bool scroll_event (Gdk.EventScroll event) { 117 | 118 | switch (event.direction.to_string ()) { 119 | case "GDK_SCROLL_UP": 120 | case "GDK_SCROLL_LEFT": 121 | selected--; 122 | break; 123 | case "GDK_SCROLL_DOWN": 124 | case "GDK_SCROLL_RIGHT": 125 | selected++; 126 | break; 127 | 128 | } 129 | 130 | return false; 131 | 132 | } 133 | 134 | } 135 | -------------------------------------------------------------------------------- /src/Settings/News/NewsSource.vala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 - Nick Wilkins 3 | * 4 | * Coffee is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Coffee is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with Coffee. If not, see . 16 | */ 17 | using Gtk; 18 | 19 | namespace Settings { 20 | public class News.NewsSource : Object { 21 | 22 | private Gee.ArrayList sources = null; 23 | 24 | static NewsSource? instance = null; 25 | 26 | public string id { get; set; } 27 | public string name { get; set; } 28 | public string description { get; set; } 29 | public string category { get; set; } 30 | public string country { get; set; } 31 | public string language { get; set; } 32 | public string url { get; set; } 33 | public string besticon_url { get; set; } 34 | 35 | public signal void get_sources_completed (); 36 | 37 | public signal void new_source (NewsSource source); 38 | 39 | public NewsSource () { 40 | sources = new Gee.ArrayList(); 41 | } 42 | 43 | public static NewsSource get_default () { 44 | if (instance == null) { 45 | instance = new NewsSource (); 46 | } 47 | 48 | return instance; 49 | } 50 | 51 | public void add_source (NewsSource source) 52 | { 53 | sources.add(source); 54 | new_source (source); 55 | } 56 | 57 | public void clear () 58 | { 59 | sources.clear(); 60 | } 61 | 62 | public void parse_completed () 63 | { 64 | get_sources_completed (); 65 | } 66 | 67 | public Gee.ArrayList get_sources () { 68 | if(sources == null){ 69 | return new Gee.ArrayList(); 70 | } 71 | 72 | return sources; 73 | } 74 | 75 | public int get_count () { 76 | return sources.size; 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/Settings/SettingsWindow.vala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017 - Nick Wilkins 3 | * 4 | * Coffee is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Coffee is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with Coffee. If not, see . 16 | */ 17 | using Gtk; 18 | using Geocode; 19 | 20 | namespace Settings { 21 | public class SettingsWindow : Window { 22 | public Coffee.CoffeeBar bar {get;construct;} 23 | 24 | private Settings settings; 25 | private Gtk.Grid grid; 26 | private Gtk.Stack stack; 27 | private News.NewsGrid news_grid; 28 | private Weather.LocationGrid location_grid; 29 | private General.AboutGrid about_grid; 30 | private Coffee.MessageDialog welcome_dialog; 31 | public bool is_open = false; 32 | 33 | 34 | public SettingsWindow (Coffee.CoffeeBar bar) { 35 | Object(bar: bar); 36 | this.transient_for = bar; 37 | settings = new Settings (); 38 | 39 | this.destroy.connect (() => { 40 | is_open = false; 41 | }); 42 | } 43 | 44 | public void setup_ui (){ 45 | this.title = "Settings"; 46 | 47 | // Sets the default size of a window: 48 | this.set_default_size (900, 600); 49 | this.window_position = Gtk.WindowPosition.CENTER; 50 | this.hide_titlebar_when_maximized = false; 51 | 52 | if(settings.first_load_bool) { 53 | welcome_dialog = new Coffee.MessageDialog.with_image_from_icon_name (this, "Welcome", "Please select news feeds and location to begin ...", "dialog-information" , Gtk.ButtonsType.OK ); 54 | welcome_dialog.show_all(); 55 | welcome_dialog.response.connect (on_response); 56 | } 57 | 58 | if(settings.get_news_count() == 0 && !settings.first_load_bool){ 59 | welcome_dialog = new Coffee.MessageDialog.with_image_from_icon_name (this, "Select News Sources", "You have no selected news items, please choose some ...", "dialog-information" , Gtk.ButtonsType.OK ); 60 | welcome_dialog.show_all(); 61 | welcome_dialog.response.connect (on_response); 62 | 63 | settings.first_load_bool = true; 64 | } 65 | 66 | grid = new Gtk.Grid (); 67 | grid.margin = 12; 68 | 69 | news_grid = new News.NewsGrid (); 70 | about_grid = new General.AboutGrid (); 71 | location_grid = new Weather.LocationGrid (); 72 | 73 | news_grid.button_add.clicked.connect(() => { 74 | var news_sources_window = new News.NewsSourcesList (this); 75 | news_sources_window.show_all(); 76 | news_sources_window.news_added.connect(() => { 77 | news_grid.refresh_news_items(); 78 | //news_sources_window.close(); 79 | }); 80 | }); 81 | 82 | news_grid.button_refresh.clicked.connect(() => { 83 | bar.reload_posts(); 84 | }); 85 | 86 | news_grid.button_launch.clicked.connect(() => { 87 | //var coffeebar = new Coffee.CoffeeBar(this.get_application()); 88 | bar.launch(); 89 | 90 | settings.first_load_bool = false; 91 | this.destroy(); 92 | }); 93 | 94 | stack = new Gtk.Stack (); 95 | //stack.add_titled (about_grid, "general", "General"); 96 | stack.add_titled (news_grid, "news", "News"); 97 | stack.add_titled (location_grid, "location", "Weather"); 98 | 99 | var stack_switcher = new Gtk.StackSwitcher (); 100 | stack_switcher.stack = stack; 101 | stack_switcher.halign = Gtk.Align.CENTER; 102 | stack_switcher.margin = 24; 103 | 104 | stack.transition_type = Gtk.StackTransitionType.SLIDE_LEFT_RIGHT; 105 | 106 | grid.attach (stack_switcher, 0, 0, 1, 1); 107 | grid.attach (stack, 0, 2, 1, 1); 108 | 109 | this.add (grid); 110 | } 111 | 112 | public void open() { 113 | if(!is_open) { 114 | setup_ui(); 115 | this.show_all(); 116 | is_open = true; 117 | } 118 | } 119 | 120 | private void on_response (Gtk.Dialog source, int response_id) { 121 | switch (response_id) { 122 | case Gtk.ResponseType.OK: 123 | welcome_dialog.close (); 124 | break; 125 | } 126 | } 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /src/Settings/Weather/LocationGrid.vala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017 - Nick Wilkins 3 | * 4 | * Coffee is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Coffee is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with Coffee. If not, see . 16 | */ 17 | using Gtk; 18 | 19 | namespace Settings { 20 | public class Weather.LocationGrid : Grid { 21 | 22 | private Gtk.SearchEntry location_entry; 23 | private Gtk.Switch _switch_location; 24 | private Gtk.Switch _switch_weather; 25 | private Gtk.Switch _switch_dark_sky; 26 | private Gtk.Switch _switch_openweathermap; 27 | private Gtk.Image location_error; 28 | private Gtk.Spinner loading_spinner; 29 | 30 | private GLib.Cancellable search_cancellable; 31 | private Settings settings; 32 | 33 | public LocationGrid () { 34 | column_spacing = 12; 35 | halign = Gtk.Align.CENTER; 36 | row_spacing = 6; 37 | margin_start = margin_end = 6; 38 | 39 | settings = Settings.get_default (); 40 | location_entry = new Gtk.SearchEntry (); 41 | _switch_location = new Gtk.Switch (); 42 | _switch_weather = new Gtk.Switch (); 43 | 44 | _switch_dark_sky = new Gtk.Switch (); 45 | _switch_openweathermap = new Gtk.Switch (); 46 | 47 | if(settings.get_location_bool) 48 | _switch_location.active = true; 49 | if(settings.dark_sky_bool) 50 | _switch_dark_sky.active = true; 51 | if(settings.open_weather_bool) 52 | _switch_openweathermap.active = true; 53 | 54 | _switch_openweathermap.halign = Gtk.Align.END; 55 | _switch_dark_sky.halign = Gtk.Align.END; 56 | _switch_location.halign = Gtk.Align.END; 57 | _switch_weather.halign = Gtk.Align.END; 58 | 59 | if(settings.location_name_string == "") 60 | location_entry.placeholder_text = "London, UK"; 61 | else 62 | location_entry.placeholder_text = settings.location_name_string; 63 | 64 | loading_spinner = new Gtk.Spinner (); 65 | loading_spinner.active = false; 66 | 67 | location_entry.hexpand = true; 68 | location_entry.margin_left = 15; 69 | location_entry.activate.connect (() => {compute_location.begin (location_entry.text);}); 70 | 71 | /*grid_1.margin = 5; 72 | grid_1.attach(new Gtk.Label("Location"), 0, 0, 1, 1); 73 | grid_1.attach(location_entry, 1, 0, 1, 1);*/ 74 | 75 | var location_label = new Gtk.Label("Location:"); 76 | location_label.halign = Gtk.Align.END; 77 | 78 | var weather_label = new Gtk.Label("Weather:"); 79 | weather_label.halign = Gtk.Align.END; 80 | 81 | var find_location_label = new Gtk.Label("Automatic Location:"); 82 | find_location_label.halign = Gtk.Align.END; 83 | 84 | var open_weather_label = new Gtk.Label("Use Open Weather Map:"); 85 | open_weather_label.halign = Gtk.Align.END; 86 | 87 | var use_dark_sky_label = new Gtk.Label("Use Dark Sky:"); 88 | use_dark_sky_label.halign = Gtk.Align.END; 89 | 90 | location_error = new Gtk.Image.from_icon_name("error", Gtk.IconSize.LARGE_TOOLBAR); 91 | use_dark_sky_label.halign = Gtk.Align.START; 92 | location_error.opacity = 0; 93 | 94 | connect_events (); 95 | //attach(weather_label, 1, 0, 1, 1); 96 | //attach(_switch_weather, 2, 0, 1, 1); 97 | attach(location_label, 1, 2, 1, 1); 98 | attach(location_entry, 2, 2, 1, 1); 99 | attach(loading_spinner, 3, 2, 1, 1); 100 | attach(location_error, 4, 2, 1, 1); 101 | attach(find_location_label, 1, 1, 1, 1); 102 | attach(_switch_location, 2, 1, 1, 1); 103 | //attach(open_weather_label, 1, 3, 1, 1); 104 | //attach(_switch_openweathermap, 2, 3, 1, 1); 105 | //attach(use_dark_sky_label, 1, 4, 1, 1); 106 | //attach(_switch_dark_sky, 2, 4, 1, 1); 107 | } 108 | 109 | private void connect_events () { 110 | _switch_location.notify["active"].connect (() => { 111 | settings.change_setting_bool(_switch_location.active, settings.get_geo_location); 112 | location_entry.sensitive = !_switch_location.active; 113 | }); 114 | _switch_openweathermap.notify["active"].connect (() => { 115 | settings.change_setting_bool(_switch_openweathermap.active, settings.open_weather_string); 116 | }); 117 | _switch_dark_sky.notify["active"].connect (() => { 118 | settings.change_setting_bool(_switch_dark_sky.active, settings.dark_sky_string); 119 | }); 120 | } 121 | 122 | private async void compute_location (string loc) { 123 | if (search_cancellable != null) 124 | search_cancellable.cancel (); 125 | 126 | loading_spinner.active = true; 127 | _switch_location.active = false; 128 | 129 | search_cancellable = new GLib.Cancellable (); 130 | var forward = new Geocode.Forward.for_string (loc); 131 | try { 132 | forward.set_answer_count (1); 133 | var places = yield forward.search_async (search_cancellable); 134 | foreach (var place in places) { 135 | settings.change_setting_string(place.name, settings.location_string); 136 | settings.change_setting_string(place.location.latitude.to_string() +","+ place.location.longitude.to_string(), settings.geolocation_string); 137 | } 138 | location_entry.has_focus = true; 139 | location_error.opacity = 0; 140 | loading_spinner.active = false; 141 | } catch (GLib.Error error) { 142 | location_error.opacity = 1; 143 | location_error.set_tooltip_text(error.message); 144 | loading_spinner.active = false; 145 | warning (error.message); 146 | } 147 | } 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /src/Views/NewsView.vala: -------------------------------------------------------------------------------- 1 | /* 2 | * NewsView.vala 3 | * This file is part of Coffee 4 | * 5 | * Copyright (C) 2018 - Nick Wilkins 6 | * 7 | * Coffee is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * news is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with Coffee. If not, see . 19 | */ 20 | 21 | using Gtk; 22 | 23 | namespace Coffee { 24 | public class Views.NewsView : Stack { 25 | Widgets.NewsFlowBox news_flow; 26 | Widgets.WeatherHeaderFlowBox weather_header_flow; 27 | private Gtk.ScrolledWindow news_scrolled; 28 | 29 | construct { 30 | news_flow = new Widgets.NewsFlowBox (); 31 | weather_header_flow = new Widgets.WeatherHeaderFlowBox (); 32 | 33 | var box_view = new Gtk.Box (Gtk.Orientation.VERTICAL, 0); 34 | box_view.add (weather_header_flow); 35 | box_view.add (news_flow); 36 | 37 | news_scrolled = new Gtk.ScrolledWindow (null, null); 38 | news_scrolled.set_overlay_scrolling(true); 39 | news_scrolled.add (box_view); 40 | 41 | add (news_scrolled); 42 | } 43 | 44 | public void clear_rows () 45 | { 46 | news_flow.clear(); 47 | weather_header_flow.clear(); 48 | } 49 | 50 | public void on_launch_url (string uri) 51 | { 52 | try { 53 | AppInfo.launch_default_for_uri (uri, null); 54 | } catch (Error e) { 55 | warning ("%s\n", e.message); 56 | } 57 | } 58 | 59 | public void add_post (Coffee.Post post) { 60 | news_flow.add_post (post); 61 | } 62 | 63 | public void add_weather_header (Coffee.Weather weather) { 64 | weather_header_flow.add_weather (weather); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/Views/WeatherView.vala: -------------------------------------------------------------------------------- 1 | /* 2 | * HomeView.vala 3 | * This file is part of Coffee 4 | * 5 | * Copyright (C) 2018 - Nick Wilkins 6 | * 7 | * Coffee is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * news is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with Coffee. If not, see . 19 | */ 20 | 21 | using Gtk; 22 | 23 | namespace Coffee { 24 | public class Views.WeatherView : Stack { 25 | Widgets.WeatherFlowBox weather_flow; 26 | private Gtk.ScrolledWindow weather_scrolled; 27 | 28 | construct { 29 | weather_flow = new Widgets.WeatherFlowBox (); 30 | 31 | weather_scrolled = new Gtk.ScrolledWindow (null, null); 32 | weather_scrolled.set_overlay_scrolling(true); 33 | weather_scrolled.add (weather_flow); 34 | 35 | add (weather_scrolled); 36 | } 37 | 38 | public void add_weather (Coffee.Weather weather) { 39 | weather_flow.add_weather (weather); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/Weather.vala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017 - Nick Wilkins 3 | * 4 | * Coffee is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * Coffee is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with Coffee. If not, see . 16 | */ 17 | using Gtk; 18 | 19 | namespace Coffee { 20 | public class Weather : Object { 21 | public string weather_img {get; set;} 22 | public string icon {get;set;} 23 | public string location {get; set;} 24 | public string temp {get; set;} 25 | public string text {get; set;} 26 | public string summary {get; set;} 27 | public string link {get; set;} 28 | public string day {get; set;} 29 | public string percip {get;set;} 30 | 31 | private Gee.ArrayList forecast = null; 32 | 33 | static Weather? instance = null; 34 | 35 | public signal void got_weather (); 36 | 37 | public Weather (){ 38 | forecast = new Gee.ArrayList (); 39 | } 40 | 41 | public void got_weather_complete () { 42 | got_weather(); 43 | } 44 | 45 | public static Weather get_default (){ 46 | if(instance == null) 47 | instance = new Weather (); 48 | 49 | return instance; 50 | } 51 | 52 | public void add_day (Weather weather) 53 | { 54 | forecast.add(weather); 55 | } 56 | 57 | public void clear_forecast () 58 | { 59 | forecast.clear(); 60 | } 61 | 62 | public Gee.ArrayList get_forecast () { 63 | if(forecast == null){ 64 | return new Gee.ArrayList (); 65 | } 66 | return forecast; 67 | } 68 | 69 | public int get_forecast_count () { 70 | return forecast.size; 71 | } 72 | } 73 | 74 | public class Forecast : Object { 75 | public string weather_img {get; set;} 76 | public int64 temp {get; set;} 77 | public string day {get; set;} 78 | 79 | private Gee.ArrayList days = null; 80 | 81 | static Forecast? instance = null; 82 | 83 | public signal void got_forecast(); 84 | 85 | public Forecast (){ 86 | days = new Gee.ArrayList(); 87 | } 88 | 89 | public static Forecast get_default(){ 90 | if(instance == null) 91 | instance = new Forecast (); 92 | 93 | return instance; 94 | } 95 | 96 | public void add_day (Forecast forecast) 97 | { 98 | days.add(forecast); 99 | } 100 | 101 | public void clear_forecast () 102 | { 103 | days.clear(); 104 | } 105 | 106 | public void get_forecast_complete() 107 | { 108 | got_forecast(); 109 | } 110 | 111 | public Gee.ArrayList get_forecast () { 112 | if(days == null){ 113 | return new Gee.ArrayList(); 114 | } 115 | 116 | return days; 117 | } 118 | 119 | public int get_count () { 120 | return days.size; 121 | } 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/Widgets/NewsFlowBox.vala: -------------------------------------------------------------------------------- 1 | // -*- Mode: vala; indent-tabs-mode: nil; tab-width: 4 -*- 2 | /*- 3 | * Copyright (c) 2014-2017 elementary LLC. (https://elementary.io) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | * Authored by: Corentin Noël 19 | */ 20 | /* Taken from elementary AppCenter */ 21 | public class Coffee.Widgets.NewsFlowBox : Gtk.FlowBox { 22 | private Coffee.Post post; 23 | 24 | public NewsFlowBox () { 25 | Object (activate_on_single_click: true, 26 | homogeneous: false, 27 | margin_start: 12, 28 | margin_top: 10, 29 | margin_end: 10, 30 | margin_bottom: 12, 31 | max_children_per_line: 1); 32 | } 33 | 34 | construct { 35 | this.child_activated.connect ((child) => { 36 | var item = child as Widgets.NewsItem; 37 | if (item != null) { 38 | on_launch_url (item.post.link); 39 | } 40 | }); 41 | } 42 | 43 | public void on_launch_url (string uri){ 44 | try { 45 | AppInfo.launch_default_for_uri (uri, null); 46 | } catch (Error e) { 47 | warning ("%s\n", e.message); 48 | } 49 | } 50 | 51 | public void clear () 52 | { 53 | if(get_children ().length().to_string().to_int() > 0){ 54 | get_children ().foreach ((child) => { 55 | remove (child); 56 | }); 57 | } 58 | } 59 | 60 | public void add_post (Coffee.Post post) 61 | { 62 | add (get_category (post)); 63 | } 64 | 65 | public void add_weather (Coffee.Weather weather) 66 | { 67 | add (get_weather_item (weather)); 68 | } 69 | 70 | private Widgets.WeatherHeaderItem get_weather_item (Coffee.Weather weather) { 71 | var item = new Widgets.WeatherHeaderItem (weather); 72 | return item; 73 | } 74 | 75 | private Widgets.NewsItem get_category (Coffee.Post post) { 76 | var item = new Widgets.NewsItem (post); 77 | 78 | return item; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/Widgets/NewsItem.vala: -------------------------------------------------------------------------------- 1 | // -*- Mode: vala; indent-tabs-mode: nil; tab-width: 4 -*- 2 | /*- 3 | * Copyright (c) 2014-2016 elementary LLC. (https://elementary.io) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | * Authored by: Corentin Noël 19 | */ 20 | /* Taken from elementary AppCenter */ 21 | public class Coffee.Widgets.NewsItem : Gtk.FlowBoxChild { 22 | public Coffee.Post post { get; construct; } 23 | private Gtk.Label news_label; 24 | private Gtk.Label title_label; 25 | private Gtk.Label description_label; 26 | private Gtk.Label author_label; 27 | private Gtk.Grid themed_grid; 28 | 29 | public NewsItem (Coffee.Post post) { 30 | Object (post: post); 31 | } 32 | 33 | construct { 34 | var display_image = new Gtk.Image (); 35 | 36 | if(post.link != "") 37 | display_image = load_new_image (post.image_link); 38 | 39 | news_label = new Gtk.Label (null); 40 | news_label.wrap = true; 41 | news_label.max_width_chars = 25; 42 | news_label.get_style_context ().add_class ("h1"); 43 | news_label.justify = Gtk.Justification.CENTER; 44 | news_label.halign = Gtk.Align.FILL; 45 | 46 | news_label.label = post.title ?? ""; 47 | 48 | description_label = new Gtk.Label (null); 49 | description_label.wrap = true; 50 | description_label.max_width_chars = 35; 51 | description_label.get_style_context ().add_class ("h2"); 52 | description_label.justify = Gtk.Justification.CENTER; 53 | description_label.halign = Gtk.Align.FILL; 54 | 55 | description_label.label = post.subject ?? ""; 56 | 57 | author_label = new Gtk.Label (null); 58 | author_label.wrap = true; 59 | //author_label.max_width_chars = 15; 60 | author_label.get_style_context ().add_class ("h3"); 61 | //author_label.justify = Gtk.Justification.RIGHT; 62 | author_label.halign = Gtk.Align.END; 63 | 64 | author_label.label = post.author ?? ""; 65 | 66 | var grid = new Gtk.Grid (); 67 | grid.orientation = Gtk.Orientation.VERTICAL; 68 | grid.row_spacing = 12; 69 | //grid.column_spacing = 8; 70 | grid.halign = Gtk.Align.CENTER; 71 | grid.valign = Gtk.Align.CENTER; 72 | grid.margin_top = 10; 73 | grid.margin_end = 10; 74 | grid.margin_bottom = 10; 75 | grid.margin_start = 10; 76 | 77 | /*grid.attach (news_label, 0, 0, 2, 1); 78 | grid.attach (description_label, 0, 1, 1, 1); 79 | grid.attach (display_image, 1, 1, 1, 1); 80 | grid.attach (author_label, 0, 2, 2, 1);*/ 81 | 82 | grid.add (news_label); 83 | grid.add (display_image); 84 | grid.add (description_label); 85 | grid.add (author_label); 86 | 87 | var expanded_grid = new Gtk.Grid (); 88 | expanded_grid.expand = true; 89 | expanded_grid.margin = 12; 90 | 91 | themed_grid = new Gtk.Grid (); 92 | //themed_grid.get_style_context ().add_class ("category"); 93 | themed_grid.attach (grid, 0, 0, 1, 1); 94 | themed_grid.attach (expanded_grid, 0, 0, 1, 1); 95 | themed_grid.margin = 10; 96 | 97 | child = themed_grid; 98 | 99 | /*tooltip_text = app_category.summary ?? ""; */ 100 | 101 | show_all (); 102 | 103 | } 104 | 105 | public void add_post (string theme_name) { 106 | //themed_grid.get_style_context ().add_class (theme_name); 107 | news_label.label = post.title; 108 | news_label.justify = Gtk.Justification.CENTER; 109 | } 110 | 111 | // We need to first download the screenshot locally so that it doesn't freeze the interface. 112 | private Gtk.Image load_new_image (string url) { 113 | var image = new Gtk.Image (); 114 | var ret = GLib.DirUtils.create_with_parents (GLib.Environment.get_tmp_dir () + Path.DIR_SEPARATOR_S + ".coffee", 0755); 115 | if (ret == -1) { 116 | critical ("Error creating the temporary folder: GFileError #%d", GLib.FileUtils.error_from_errno (GLib.errno)); 117 | } 118 | 119 | string path = Path.build_path (Path.DIR_SEPARATOR_S, GLib.Environment.get_tmp_dir (), ".coffee", "XXXXXX"); 120 | File fileimage; 121 | var fd = GLib.FileUtils.mkstemp (path); 122 | if (fd != -1) { 123 | var source = File.new_for_uri (url); 124 | fileimage = File.new_for_path (path); 125 | try { 126 | source.copy (fileimage, GLib.FileCopyFlags.OVERWRITE); 127 | } catch (Error e) { 128 | debug (e.message); 129 | return null; 130 | } 131 | 132 | GLib.FileUtils.close (fd); 133 | } else { 134 | critical ("Error create the temporary file: GFileError #%d", GLib.FileUtils.error_from_errno (GLib.errno)); 135 | fileimage = File.new_for_uri (url); 136 | if (fileimage.query_exists () == false) { 137 | return null; 138 | } 139 | } 140 | 141 | Idle.add (() => { 142 | try { 143 | //image.width_request = 80; 144 | //image.height_request = 50; 145 | image.icon_name = "image-x-generic"; 146 | image.halign = Gtk.Align.CENTER; 147 | image.pixbuf = new Gdk.Pixbuf.from_file_at_scale (fileimage.get_path (), 300, 150, true); 148 | //image.show (); 149 | } catch (Error e) { 150 | critical (e.message); 151 | } 152 | 153 | return GLib.Source.REMOVE; 154 | }); 155 | 156 | return image; 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /src/Widgets/Selector.vala: -------------------------------------------------------------------------------- 1 | /* 2 | * CoffeeBar.vala 3 | * This file is part of Coffee 4 | * 5 | * Copyright (C) 2017 - Nick Wilkins 6 | * 7 | * Coffee is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * Coffee is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with Coffee. If not, see . 19 | */ 20 | 21 | using Gtk; 22 | 23 | public enum Coffee.Widgets.Modality { 24 | NEWS_VIEW = 0, 25 | WEATHER_VIEW = 1 26 | } 27 | 28 | public class Coffee.Widgets.Selector : Gtk.ButtonBox { 29 | 30 | public signal void mode_changed(); 31 | 32 | private int _selected; 33 | public int selected { 34 | get { 35 | return this._selected; 36 | } 37 | set { 38 | this.set_selector(value); 39 | } 40 | } 41 | 42 | //private Gtk.ToggleButton view_all; 43 | private Gtk.ToggleButton view_news; 44 | private Gtk.ToggleButton view_weather; 45 | 46 | public Selector(Gtk.Orientation orientation) { 47 | 48 | this._selected = -1; 49 | this.set_orientation(orientation); 50 | this.set_layout(Gtk.ButtonBoxStyle.CENTER); 51 | this.margin_top = 10; 52 | this.margin_bottom = 10; 53 | 54 | view_news = new Gtk.ToggleButton(); 55 | view_news.set_relief(Gtk.ReliefStyle.NONE); 56 | var image = new Gtk.Image.from_icon_name ("x-office-document-symbolic", Gtk.IconSize.MENU); 57 | image.tooltip_text = _("News View"); 58 | 59 | view_news.add(image); 60 | this.pack_start (view_news,false,false,0); 61 | 62 | view_weather = new Gtk.ToggleButton(); 63 | var stared_image = new Gtk.Image.from_icon_name ("weather-few-clouds-symbolic", Gtk.IconSize.MENU); 64 | stared_image.tooltip_text = _("Weather View"); 65 | view_weather.set_relief(Gtk.ReliefStyle.NONE); 66 | view_weather.add(stared_image); 67 | this.pack_start(view_weather,false,false,0); 68 | 69 | view_news.button_release_event.connect( (bt) => { 70 | this.set_selector(0); 71 | return true; 72 | }); 73 | view_weather.button_release_event.connect( (bt) => { 74 | this.set_selector(1); 75 | return true; 76 | }); 77 | } 78 | 79 | public int get_selector() { 80 | return this._selected; 81 | } 82 | 83 | public void set_selector(int v) { 84 | if (this._selected != v) { 85 | this._selected = v; 86 | switch(v) { 87 | case 0: 88 | this.view_news.set_active(true); 89 | this.view_weather.set_active(false); 90 | break; 91 | case 1: 92 | this.view_weather.set_active(true); 93 | this.view_news.set_active(false); 94 | break; 95 | } 96 | 97 | this.mode_changed(); 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/Widgets/WeatherFlowBox.vala: -------------------------------------------------------------------------------- 1 | // -*- Mode: vala; indent-tabs-mode: nil; tab-width: 4 -*- 2 | /*- 3 | * Copyright (c) 2014-2017 elementary LLC. (https://elementary.io) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | * Authored by: Corentin Noël 19 | */ 20 | /* Taken from elementary AppCenter */ 21 | public class Coffee.Widgets.WeatherFlowBox : Gtk.FlowBox { 22 | //private Coffee.Weather weather; 23 | 24 | public WeatherFlowBox () { 25 | Object (activate_on_single_click: true, 26 | homogeneous: false, 27 | margin_start: 12, 28 | margin_top: 10, 29 | margin_end: 10, 30 | margin_bottom: 12, 31 | max_children_per_line: 1); 32 | } 33 | 34 | public void add_weather (Coffee.Weather weather) 35 | { 36 | add (get_weather_item (weather)); 37 | } 38 | 39 | public void clear () 40 | { 41 | if(get_children ().length().to_string().to_int() > 0){ 42 | get_children ().foreach ((child) => { 43 | remove (child); 44 | }); 45 | } 46 | } 47 | 48 | private Widgets.WeatherItem get_weather_item (Coffee.Weather weather) { 49 | var item = new Widgets.WeatherItem (weather); 50 | //item.add_category_class (style); 51 | return item; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/Widgets/WeatherHeaderFlow.vala: -------------------------------------------------------------------------------- 1 | // -*- Mode: vala; indent-tabs-mode: nil; tab-width: 4 -*- 2 | /*- 3 | * Copyright (c) 2014-2017 elementary LLC. (https://elementary.io) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | * Authored by: Corentin Noël 19 | */ 20 | /* Taken from elementary AppCenter */ 21 | public class Coffee.Widgets.WeatherHeaderFlowBox : Gtk.FlowBox { 22 | private Coffee.Weather post; 23 | 24 | public WeatherHeaderFlowBox () { 25 | Object (activate_on_single_click: true, 26 | homogeneous: false, 27 | margin_start: 12, 28 | margin_top: 10, 29 | margin_end: 10, 30 | margin_bottom: 12, 31 | max_children_per_line: 1); 32 | } 33 | 34 | construct { 35 | this.child_activated.connect ((child) => { 36 | var item = child as Widgets.WeatherHeaderItem; 37 | if (item != null) { 38 | //on_launch_url (item.link); 39 | } 40 | }); 41 | } 42 | 43 | public void clear () { 44 | if(get_children ().length().to_string().to_int() > 0){ 45 | get_children ().foreach ((child) => { 46 | remove (child); 47 | }); 48 | } 49 | } 50 | 51 | public void add_weather (Coffee.Weather weather) 52 | { 53 | add (get_weather_item (weather)); 54 | } 55 | 56 | private Widgets.WeatherHeaderItem get_weather_item (Coffee.Weather weather) { 57 | var item = new Widgets.WeatherHeaderItem (weather); 58 | return item; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/Widgets/WeatherHeaderItem.vala: -------------------------------------------------------------------------------- 1 | // -*- Mode: vala; indent-tabs-mode: nil; tab-width: 4 -*- 2 | /*- 3 | * Copyright (c) 2014-2016 elementary LLC. (https://elementary.io) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | * Authored by: Corentin Noël 19 | */ 20 | /* Taken from elementary AppCenter */ 21 | public class Coffee.Widgets.WeatherHeaderItem : Gtk.FlowBoxChild { 22 | public Coffee.Weather weather { get; construct; } 23 | private Gtk.Label detail_label; 24 | private Gtk.Label title_label; 25 | private Gtk.Label description_label; 26 | private Gtk.Label temp_label; 27 | private Gtk.Label percip_label; 28 | private Gtk.Grid themed_grid; 29 | 30 | public WeatherHeaderItem (Coffee.Weather weather) { 31 | Object (weather: weather); 32 | } 33 | 34 | construct { 35 | var display_image = new Gtk.Image (); 36 | 37 | if(weather.weather_img != null && weather.weather_img != "") 38 | display_image = load_new_image (weather.weather_img, weather.icon); 39 | 40 | title_label = new Gtk.Label (null); 41 | title_label.wrap = true; 42 | title_label.max_width_chars = 25; 43 | title_label.get_style_context ().add_class ("h1"); 44 | title_label.justify = Gtk.Justification.CENTER; 45 | title_label.halign = Gtk.Align.FILL; 46 | 47 | title_label.label = weather.day ?? ""; 48 | 49 | description_label = new Gtk.Label (null); 50 | description_label.wrap = true; 51 | description_label.max_width_chars = 35; 52 | description_label.get_style_context ().add_class ("h1"); 53 | description_label.justify = Gtk.Justification.CENTER; 54 | description_label.halign = Gtk.Align.FILL; 55 | 56 | description_label.label = weather.summary ?? ""; 57 | 58 | temp_label = new Gtk.Label (null); 59 | temp_label.wrap = true; 60 | //temp_label.max_width_chars = 15; 61 | temp_label.get_style_context ().add_class ("h3"); 62 | temp_label.justify = Gtk.Justification.LEFT; 63 | temp_label.halign = Gtk.Align.START; 64 | 65 | temp_label.label = weather.temp.to_string (); 66 | 67 | percip_label = new Gtk.Label (null); 68 | percip_label.wrap = true; 69 | percip_label.get_style_context ().add_class ("h3"); 70 | percip_label.justify = Gtk.Justification.LEFT; 71 | percip_label.halign = Gtk.Align.START; 72 | 73 | percip_label.label = weather.percip.to_string (); 74 | 75 | var grid = new Gtk.Grid (); 76 | grid.orientation = Gtk.Orientation.VERTICAL; 77 | grid.row_spacing = 10; 78 | //grid.column_spacing = 8; 79 | grid.halign = Gtk.Align.CENTER; 80 | grid.valign = Gtk.Align.CENTER; 81 | grid.margin_top = 10; 82 | grid.margin_end = 10; 83 | grid.margin_bottom = 10; 84 | grid.margin_start = 10; 85 | 86 | var centre_grid = new Gtk.Grid (); 87 | centre_grid.expand = true; 88 | centre_grid.margin = 10; 89 | centre_grid.row_spacing = 5; 90 | centre_grid.column_spacing = 20; 91 | 92 | centre_grid.attach (display_image, 0, 0, 1, 2); 93 | centre_grid.attach (temp_label, 1, 0, 1, 1); 94 | centre_grid.attach (percip_label, 1, 1, 1, 1); 95 | 96 | /*grid.attach (news_label, 0, 0, 2, 1); 97 | grid.attach (description_label, 0, 1, 1, 1); 98 | grid.attach (display_image, 1, 1, 1, 1); 99 | grid.attach (author_label, 0, 2, 2, 1);*/ 100 | 101 | grid.attach (description_label, 0, 0, 1, 1); 102 | grid.attach (centre_grid, 0, 1, 1, 1); 103 | //grid.add (description_label); 104 | //grid.attach (temp_label, 1, 1, 1, 1); 105 | 106 | var expanded_grid = new Gtk.Grid (); 107 | expanded_grid.expand = true; 108 | expanded_grid.margin = 12; 109 | 110 | themed_grid = new Gtk.Grid (); 111 | //themed_grid.get_style_context ().add_class ("category"); 112 | themed_grid.attach (grid, 0, 0, 1, 1); 113 | themed_grid.attach (expanded_grid, 0, 0, 1, 1); 114 | themed_grid.margin = 10; 115 | 116 | child = themed_grid; 117 | 118 | show_all (); 119 | } 120 | 121 | // We need to first download the screenshot locally so that it doesn't freeze the interface. 122 | private Gtk.Image load_new_image (string url, string icon) { 123 | var image = new Gtk.Image (); 124 | var ret = GLib.DirUtils.create_with_parents (GLib.Environment.get_user_cache_dir () + Path.DIR_SEPARATOR_S + "com.github.nick92.coffee" + Path.DIR_SEPARATOR_S + "weather_icons", 0755); 125 | if (ret == -1) { 126 | critical ("Error creating the temporary folder: GFileError #%d", GLib.FileUtils.error_from_errno (GLib.errno)); 127 | } 128 | 129 | string path = Path.build_path (Path.DIR_SEPARATOR_S, GLib.Environment.get_user_cache_dir (), "com.github.nick92.coffee", "weather_icons"); 130 | File fileimage; 131 | var source = File.new_for_uri (url); 132 | fileimage = File.new_for_path (path + Path.DIR_SEPARATOR_S + icon); 133 | try { 134 | if(!fileimage.query_exists ()){ 135 | source.copy (fileimage, GLib.FileCopyFlags.OVERWRITE); 136 | } 137 | } catch (Error e) { 138 | debug (e.message); 139 | return null; 140 | } 141 | 142 | Idle.add (() => { 143 | try { 144 | //image.width_request = 80; 145 | //image.height_request = 50; 146 | image.icon_name = "image-x-generic"; 147 | image.halign = Gtk.Align.CENTER; 148 | image.pixbuf = new Gdk.Pixbuf.from_file_at_scale (fileimage.get_path (), 90, 60, true); 149 | //image.show (); 150 | } catch (Error e) { 151 | critical (e.message); 152 | } 153 | 154 | return GLib.Source.REMOVE; 155 | }); 156 | 157 | return image; 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /src/Widgets/WeatherItem.vala: -------------------------------------------------------------------------------- 1 | // -*- Mode: vala; indent-tabs-mode: nil; tab-width: 4 -*- 2 | /*- 3 | * Copyright (c) 2014-2016 elementary LLC. (https://elementary.io) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | * Authored by: Corentin Noël 19 | */ 20 | /* Taken from elementary AppCenter */ 21 | public class Coffee.Widgets.WeatherItem : Gtk.FlowBoxChild { 22 | public Coffee.Weather weather { get; construct; } 23 | private Gtk.Label news_label; 24 | private Gtk.Label title_label; 25 | private Gtk.Label description_label; 26 | private Gtk.Label author_label; 27 | private Gtk.Grid themed_grid; 28 | 29 | public WeatherItem (Coffee.Weather weather) { 30 | Object (weather: weather); 31 | } 32 | 33 | construct { 34 | var display_image = new Gtk.Image (); 35 | 36 | if(weather.weather_img != null && weather.weather_img != "") 37 | display_image = load_new_image (weather.weather_img); 38 | 39 | news_label = new Gtk.Label (null); 40 | news_label.wrap = true; 41 | news_label.max_width_chars = 25; 42 | news_label.get_style_context ().add_class ("h1"); 43 | news_label.justify = Gtk.Justification.CENTER; 44 | news_label.halign = Gtk.Align.FILL; 45 | 46 | news_label.label = weather.day ?? ""; 47 | 48 | description_label = new Gtk.Label (null); 49 | description_label.wrap = true; 50 | description_label.max_width_chars = 35; 51 | description_label.get_style_context ().add_class ("h2"); 52 | description_label.justify = Gtk.Justification.CENTER; 53 | description_label.halign = Gtk.Align.FILL; 54 | 55 | description_label.label = weather.summary ?? ""; 56 | 57 | author_label = new Gtk.Label (null); 58 | author_label.wrap = true; 59 | author_label.max_width_chars = 15; 60 | author_label.get_style_context ().add_class ("h3"); 61 | author_label.justify = Gtk.Justification.RIGHT; 62 | author_label.halign = Gtk.Align.END; 63 | 64 | author_label.label = weather.temp.to_string (); 65 | 66 | var grid = new Gtk.Grid (); 67 | grid.orientation = Gtk.Orientation.VERTICAL; 68 | grid.row_spacing = 10; 69 | //grid.column_spacing = 8; 70 | grid.halign = Gtk.Align.CENTER; 71 | grid.valign = Gtk.Align.CENTER; 72 | grid.margin_top = 10; 73 | grid.margin_end = 10; 74 | grid.margin_bottom = 10; 75 | grid.margin_start = 10; 76 | 77 | /*grid.attach (news_label, 0, 0, 2, 1); 78 | grid.attach (description_label, 0, 1, 1, 1); 79 | grid.attach (display_image, 1, 1, 1, 1); 80 | grid.attach (author_label, 0, 2, 2, 1);*/ 81 | 82 | grid.add (news_label); 83 | grid.add (display_image); 84 | grid.add (description_label); 85 | grid.add (author_label); 86 | 87 | var expanded_grid = new Gtk.Grid (); 88 | expanded_grid.expand = true; 89 | expanded_grid.margin = 12; 90 | 91 | themed_grid = new Gtk.Grid (); 92 | //themed_grid.get_style_context ().add_class ("category"); 93 | themed_grid.attach (grid, 0, 0, 1, 1); 94 | themed_grid.attach (expanded_grid, 0, 0, 1, 1); 95 | themed_grid.margin = 10; 96 | 97 | child = themed_grid; 98 | 99 | /*tooltip_text = app_category.summary ?? ""; */ 100 | 101 | show_all (); 102 | } 103 | 104 | // We need to first download the screenshot locally so that it doesn't freeze the interface. 105 | private Gtk.Image load_new_image (string url) { 106 | var image = new Gtk.Image (); 107 | var ret = GLib.DirUtils.create_with_parents (GLib.Environment.get_tmp_dir () + Path.DIR_SEPARATOR_S + ".coffee", 0755); 108 | if (ret == -1) { 109 | critical ("Error creating the temporary folder: GFileError #%d", GLib.FileUtils.error_from_errno (GLib.errno)); 110 | } 111 | 112 | string path = Path.build_path (Path.DIR_SEPARATOR_S, GLib.Environment.get_tmp_dir (), ".coffee", "XXXXXX"); 113 | File fileimage; 114 | var fd = GLib.FileUtils.mkstemp (path); 115 | if (fd != -1) { 116 | var source = File.new_for_uri (url); 117 | fileimage = File.new_for_path (path); 118 | try { 119 | source.copy (fileimage, GLib.FileCopyFlags.OVERWRITE); 120 | } catch (Error e) { 121 | debug (e.message); 122 | return null; 123 | } 124 | 125 | GLib.FileUtils.close (fd); 126 | } else { 127 | critical ("Error create the temporary file: GFileError #%d", GLib.FileUtils.error_from_errno (GLib.errno)); 128 | fileimage = File.new_for_uri (url); 129 | if (fileimage.query_exists () == false) { 130 | return null; 131 | } 132 | } 133 | 134 | Idle.add (() => { 135 | try { 136 | //image.width_request = 80; 137 | //image.height_request = 50; 138 | image.icon_name = "image-x-generic"; 139 | image.halign = Gtk.Align.CENTER; 140 | image.pixbuf = new Gdk.Pixbuf.from_file_at_scale (fileimage.get_path (), 150, 100, true); 141 | //image.show (); 142 | } catch (Error e) { 143 | critical (e.message); 144 | } 145 | 146 | return GLib.Source.REMOVE; 147 | }); 148 | 149 | return image; 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /src/Worker/Retriever.vala: -------------------------------------------------------------------------------- 1 | /* 2 | * Retriever.vala 3 | * This file is part of Coffee 4 | * 5 | * Copyright (C) 2017 - Nick Wilkins 6 | * 7 | * Coffee is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * Coffee is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with Coffee. If not, see . 19 | */ 20 | using Geocode; 21 | using GLib; 22 | 23 | namespace Worker { 24 | public class Retriever : Object { 25 | 26 | Parser parser = null; 27 | Settings.Settings settings; 28 | Coffee.Post post = null; 29 | public SourceFunc callback; 30 | 31 | private string apiKey = "e8a66b24da89420b9a419849e95d47a1"; 32 | private string geolocation = ""; 33 | 34 | public Retriever () { 35 | settings = Settings.Settings.get_default(); 36 | post = Coffee.Post.get_default (); 37 | } 38 | 39 | public async void run_parser_news () { 40 | //get uri news string and pass Json message to parser 41 | foreach (string source in settings.get_news_sources_random()) { 42 | parse_message (source); 43 | } 44 | 45 | if(post != null){ 46 | post.parse_completed(); 47 | } 48 | } 49 | 50 | public async void run_parser_weather () { 51 | if(settings.weather_bool){ 52 | geolocation = settings.geo_location_string; 53 | if(geolocation != "") 54 | { 55 | if(settings.dark_sky_bool) 56 | parse_message (Sources.DARK_SKY); 57 | 58 | //if(settings.open_weather_bool) 59 | //parse_message (Sources.OPEN_WEATHER_MAP); 60 | 61 | // Idle.add(this.run_parser_weather.callback); 62 | } 63 | } 64 | // yield; 65 | } 66 | 67 | public void create_fake_news () { 68 | var new_post = new Coffee.Post(); 69 | new_post.title = "Mnuchin, Navarro got into 'screaming match' on China trip | Trump's infrastructure plan hits dead end"; 70 | new_post.image_link = "http://s.marketwatch.com/public/resources/MWimages/MW-GI625_mnuchi_ZG_20180504175155.jpg"; 71 | new_post.subject = "Top Trump aides reportedly got into a ‘screaming match’ on a China trip; President Trump’s infrastructure plan at a dead end; and what a former Treasury official said about a story involving the department and Michael Cohen."; 72 | new_post.author = "Robert Schroeder"; 73 | new_post.link = "https://www.marketwatch.com/story/mnuchin-navarro-got-into-screaming-match-on-china-trip-trumps-infrastructure-plan-hits-dead-end-2018-05-17"; 74 | 75 | post.add_post (new_post); 76 | 77 | var new_post2 = new Coffee.Post(); 78 | new_post2.title = "North Korea turns on 'incompetent' South"; 79 | new_post2.image_link = "https://ichef.bbci.co.uk/news/1024/branded_news/1011D/production/_101612856_mediaitem101612855.jpg"; 80 | new_post2.subject = "Angry at US military drills, Pyongyang says it will not talk to South Korea until issues are settled."; 81 | new_post2.author = "BBC News"; 82 | new_post2.link = "https://www.marketwatch.com/story/mnuchin-navarro-got-into-screaming-match-on-china-trip-trumps-infrastructure-plan-hits-dead-end-2018-05-17"; 83 | 84 | post.add_post (new_post2); 85 | 86 | var new_post3 = new Coffee.Post(); 87 | new_post3.title = "Girl found dead after migrant van chase"; 88 | new_post3.image_link = "https://ichef.bbci.co.uk/news/1024/branded_news/16B70/production/_101604039_gettyimages-516477472.jpg"; 89 | new_post3.subject = "A young girl's body is discovered after Belgian police pursue a van carrying up to 30 migrants, reports say"; 90 | new_post3.author = "BBC News"; 91 | new_post3.link = "https://www.marketwatch.com/story/mnuchin-navarro-got-into-screaming-match-on-china-trip-trumps-infrastructure-plan-hits-dead-end-2018-05-17"; 92 | 93 | post.add_post (new_post3); 94 | 95 | post.parse_completed(); 96 | } 97 | 98 | private void parse_message (string source) { 99 | var uri = get_source_from_uri(source); 100 | var session = new Soup.Session (); 101 | var message = new Soup.Message ("GET", uri); 102 | session.send_message (message); 103 | parser = new Parser (); 104 | parser.parse_message(message, source); 105 | } 106 | 107 | public string get_source_from_uri(string news_source) 108 | { 109 | if(news_source == Sources.DARK_SKY) 110 | return "https://api.darksky.net/forecast/06446ae7099feacb17ffef78fdf89f0a/" + geolocation + "?units=auto&exclude=[minutely,alerts,flags]"; 111 | else if (news_source == Sources.OPEN_WEATHER_MAP) { 112 | return "http://api.openweathermap.org/data/2.5/weather?lat="+geolocation.split(",")[0]+"&lon="+geolocation.split(",")[1]+"&appid=fa2392a571d54a9d17b1f0f0c934d562&units=metric"; 113 | } 114 | else { 115 | return "https://newsapi.org/v2/top-headlines?sources=" + news_source + "&apiKey=" + apiKey + ""; 116 | //return "https://newsapi.org/v1/articles?source=" + news_source + "&apiKey=" + apiKey + ""; 117 | } 118 | } 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /src/Worker/Sources.vala: -------------------------------------------------------------------------------- 1 | /* 2 | * controller.vala 3 | * This file is part of Coffee 4 | * 5 | * Copyright (C) 2017 - Nick Wilkins 6 | * 7 | * Coffee is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * news is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with Coffee. If not, see . 19 | */ 20 | 21 | namespace Worker.Sources { 22 | const string DARK_SKY = "dark-sky"; 23 | const string OPEN_WEATHER_MAP = "open-weather-map"; //TODO - add support for open weather map 24 | } 25 | -------------------------------------------------------------------------------- /src/config.vala.in: -------------------------------------------------------------------------------- 1 | namespace Build { 2 | public const string APP_NAME = "@APP_NAME@"; 3 | public const string BLACKLIST = "@BLACKLIST@"; 4 | public const string CONFIGDIR = "@CONFIGDIR@"; 5 | public const string GETTEXT_PACKAGE = "@GETTEXT_PACKAGE@"; 6 | public const string PROJECT_NAME = "@PROJECT_NAME@"; 7 | public const string VERSION = "@VERSION@"; 8 | } 9 | -------------------------------------------------------------------------------- /src/meson.build: -------------------------------------------------------------------------------- 1 | 2 | sources = [ 3 | 'Main.vala', 4 | 'CoffeeBar.vala', 5 | 'Post.vala', 6 | 'Logger.vala', 7 | 'Weather.vala', 8 | 'Views/NewsView.vala', 9 | 'Views/WeatherView.vala', 10 | 'Widgets/MessageDialog.vala', 11 | 'Widgets/NewsFlowBox.vala', 12 | 'Widgets/NewsItem.vala', 13 | 'Widgets/WeatherFlowBox.vala', 14 | 'Widgets/WeatherHeaderFlow.vala', 15 | 'Widgets/WeatherHeaderItem.vala', 16 | 'Widgets/WeatherItem.vala', 17 | 'Widgets/Selector.vala', 18 | 'Worker/Retriever.vala', 19 | 'Worker/Parser.vala', 20 | 'Worker/Sources.vala', 21 | 'Settings/Weather/LocationGrid.vala', 22 | 'Settings/General/AboutGrid.vala', 23 | 'Settings/General/StripeDialog.vala', 24 | 'Settings/News/Dialog/NewsSourcesList.vala', 25 | 'Settings/News/Dialog/NewsSourcesGet.vala', 26 | 'Settings/News/NewsSource.vala', 27 | 'Settings/News/NewsContainer.vala', 28 | 'Settings/News/Dialog/NewsListRow.vala', 29 | 'Settings/News/NewsGrid.vala', 30 | 'Settings/News/Dialog/Sidebar.vala', 31 | 'Settings/SettingsWindow.vala', 32 | 'Settings/Settings.vala', 33 | coffee_resources 34 | ] 35 | 36 | config_file = configure_file( 37 | input: 'config.vala.in', 38 | output: 'config.vala', 39 | configuration: conf_data 40 | ) 41 | 42 | executable (meson.project_name(), 43 | sources, 44 | config_file, 45 | dependencies: [glib, gtk, json, soup, gee, geocode, geoclue], 46 | vala_args:['--target-glib=2.38', '--gresources=' + meson.source_root () + '/data/coffee-resource.xml'], 47 | install: true 48 | ) 49 | -------------------------------------------------------------------------------- /vapi/keybinder-3.0.vapi: -------------------------------------------------------------------------------- 1 | [CCode (cprefix = "KEYBINDER", lower_case_cprefix = "keybinder_", cheader_filename="keybinder.h")] 2 | namespace Keybinder { 3 | [CCode (has_target=false)] 4 | public delegate void Handler (string keystring, void *udata); 5 | 6 | public void init(); 7 | public bool bind (string keystring, Handler hander, void *udata); 8 | public void unbind (string keystring, Handler handler); 9 | public uint32 get_current_event_time (); 10 | } --------------------------------------------------------------------------------