├── .bowerrc
├── .editorconfig
├── .gitignore
├── LICENSE
├── Procfile
├── README.md
├── bower.json
├── config.xml
├── docs
└── images
│ ├── doc_1.png
│ ├── doc_2.png
│ └── doc_3.png
├── gulpfile.js
├── hooks
├── README.md
├── after_prepare
│ ├── 010_add_platform_class.js
│ ├── 020_remove_sass_from_platforms.js
│ ├── 030_clean_dev_files_from_platforms.js
│ ├── 040_move_dist_files_to_platforms.js
│ └── 050_clean_obfuscation.js
└── before_prepare
│ └── 01_jshint.js
├── ionic.project
├── package.json
├── platforms
├── ios
│ ├── .gitignore
│ ├── Ruby China.xcodeproj
│ │ ├── project.pbxproj
│ │ ├── project.xcworkspace
│ │ │ ├── contents.xcworkspacedata
│ │ │ └── xcuserdata
│ │ │ │ └── jason.xcuserdatad
│ │ │ │ └── UserInterfaceState.xcuserstate
│ │ └── xcuserdata
│ │ │ └── jason.xcuserdatad
│ │ │ ├── xcdebugger
│ │ │ └── Breakpoints_v2.xcbkptlist
│ │ │ └── xcschemes
│ │ │ ├── Ruby China.xcscheme
│ │ │ └── xcschememanagement.plist
│ ├── Ruby China
│ │ ├── .gitignore
│ │ ├── Bridging-Header.h
│ │ ├── Classes
│ │ │ ├── AppDelegate.h
│ │ │ ├── AppDelegate.m
│ │ │ ├── MainViewController.h
│ │ │ ├── MainViewController.m
│ │ │ └── MainViewController.xib
│ │ ├── Images.xcassets
│ │ │ ├── AppIcon.appiconset
│ │ │ │ ├── Contents.json
│ │ │ │ ├── icon-40.png
│ │ │ │ ├── icon-40@2x.png
│ │ │ │ ├── icon-50.png
│ │ │ │ ├── icon-50@2x.png
│ │ │ │ ├── icon-60.png
│ │ │ │ ├── icon-60@2x.png
│ │ │ │ ├── icon-60@3x.png
│ │ │ │ ├── icon-72.png
│ │ │ │ ├── icon-72@2x.png
│ │ │ │ ├── icon-76.png
│ │ │ │ ├── icon-76@2x.png
│ │ │ │ ├── icon-83.5@2x.png
│ │ │ │ ├── icon-small.png
│ │ │ │ ├── icon-small@2x.png
│ │ │ │ ├── icon-small@3x.png
│ │ │ │ ├── icon.png
│ │ │ │ └── icon@2x.png
│ │ │ └── LaunchImage.launchimage
│ │ │ │ ├── Contents.json
│ │ │ │ ├── Default-568h@2x~iphone.png
│ │ │ │ ├── Default-667h.png
│ │ │ │ ├── Default-736h.png
│ │ │ │ ├── Default-Landscape-736h.png
│ │ │ │ ├── Default-Landscape@2x~ipad.png
│ │ │ │ ├── Default-Landscape~ipad.png
│ │ │ │ ├── Default-Portrait@2x~ipad.png
│ │ │ │ ├── Default-Portrait~ipad.png
│ │ │ │ ├── Default@2x~iphone.png
│ │ │ │ └── Default~iphone.png
│ │ ├── Ruby China-Info.plist
│ │ ├── Ruby China-Prefix.pch
│ │ ├── config.xml
│ │ └── main.m
│ ├── frameworks.json
│ └── ios.json
└── platforms.json
├── resources
├── android
│ ├── icon
│ │ ├── drawable-hdpi-icon.png
│ │ ├── drawable-ldpi-icon.png
│ │ ├── drawable-mdpi-icon.png
│ │ ├── drawable-xhdpi-icon.png
│ │ ├── drawable-xxhdpi-icon.png
│ │ └── drawable-xxxhdpi-icon.png
│ └── splash
│ │ ├── drawable-land-hdpi-screen.png
│ │ ├── drawable-land-ldpi-screen.png
│ │ ├── drawable-land-mdpi-screen.png
│ │ ├── drawable-land-xhdpi-screen.png
│ │ ├── drawable-land-xxhdpi-screen.png
│ │ ├── drawable-land-xxxhdpi-screen.png
│ │ ├── drawable-port-hdpi-screen.png
│ │ ├── drawable-port-ldpi-screen.png
│ │ ├── drawable-port-mdpi-screen.png
│ │ ├── drawable-port-xhdpi-screen.png
│ │ ├── drawable-port-xxhdpi-screen.png
│ │ └── drawable-port-xxxhdpi-screen.png
├── icon.png
├── icon_trans.png
├── ios
│ ├── icon
│ │ ├── icon-40.png
│ │ ├── icon-40@2x.png
│ │ ├── icon-50.png
│ │ ├── icon-50@2x.png
│ │ ├── icon-60.png
│ │ ├── icon-60@2x.png
│ │ ├── icon-60@3x.png
│ │ ├── icon-72.png
│ │ ├── icon-72@2x.png
│ │ ├── icon-76.png
│ │ ├── icon-76@2x.png
│ │ ├── icon-small.png
│ │ ├── icon-small@2x.png
│ │ ├── icon-small@3x.png
│ │ ├── icon.png
│ │ └── icon@2x.png
│ └── splash
│ │ ├── Default-568h@2x~iphone.png
│ │ ├── Default-667h.png
│ │ ├── Default-736h.png
│ │ ├── Default-Landscape-736h.png
│ │ ├── Default-Landscape@2x~ipad.png
│ │ ├── Default-Landscape~ipad.png
│ │ ├── Default-Portrait@2x~ipad.png
│ │ ├── Default-Portrait~ipad.png
│ │ ├── Default@2x~iphone.png
│ │ └── Default~iphone.png
└── splash.png
├── scss
├── _base.scss
├── _markdown.scss
├── _menu.scss
├── _notifications.scss
├── _topic.scss
├── _topics.scss
├── _user.scss
└── style.scss
└── www
├── img
├── default_avatar.png
└── ionic.png
├── index.html
├── js
├── app.js
├── controllers
│ ├── controller.module.js
│ ├── main.controller.js
│ ├── notifications.controller.js
│ ├── topic.controller.js
│ ├── topics.controller.js
│ └── user.controller.js
├── core
│ ├── config.core.js
│ ├── core.module.js
│ ├── route.core.js
│ └── run.core.js
├── filters
│ ├── exlink.filter.js
│ └── filter.module.js
└── services
│ ├── auth.service.js
│ ├── base.service.js
│ ├── camera.service.js
│ ├── service.module.js
│ ├── topic.service.js
│ └── user.service.js
└── templates
├── menu.html
├── modals
├── code_selector.html
├── login.html
├── new_topic.html
└── reply.html
├── notifications.html
├── notifications
├── follow.html
├── mention.html
├── nodechanged.html
├── topic.html
└── topicreply.html
├── topic.html
├── topics.html
└── user
└── profile.html
/.bowerrc:
--------------------------------------------------------------------------------
1 | {
2 | "directory": "www/lib"
3 | }
4 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # http://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | charset = utf-8
6 | indent_style = space
7 | indent_size = 2
8 | end_of_line = lf
9 | insert_final_newline = true
10 | trim_trailing_whitespace = true
11 |
12 | [*.md]
13 | insert_final_newline = false
14 | trim_trailing_whitespace = false
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Specifies intentionally untracked files to ignore when using Git
2 | # http://git-scm.com/docs/gitignore
3 |
4 | node_modules/
5 | platforms/ios/build
6 | platforms/ios/cordova
7 | platforms/ios/CordovaLib
8 | platforms/ios/www
9 | platforms/ios/platform_www
10 | plugins/
11 | .idea
12 | .temp
13 | .sass-cache
14 | *.swp
15 | *.swo
16 | *.log
17 | *.DS_Store
18 | www/lib
19 | www/dist/**
20 | www/css
21 | www/annotated_js/**
22 | npm-debug.log
23 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Ruby China
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 all
13 | 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 THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/Procfile:
--------------------------------------------------------------------------------
1 | ionic: ionic serve -w chrome -a
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Ruby China App
2 | Official Ruby China Mobile App for iOS and Android using Ionic framework.
3 |
4 | [](https://itunes.apple.com/cn/app/ruby-china-guan-fang-ke-hu-duan/id1072028763?mt=8)
5 |
6 | 🚀 **An refactor version according to Johnpapa's AngularJS Style, and redraw UI with Material elements**
7 | ⏳ **Additional, adding Gulp make it easy to build**
8 | 🚿 **New UI + New DE make it more fun to play Front-end Development**
9 |
10 | ## The 1st Major Release (Progress)
11 | 1. User Login / Logout(100%)
12 | 2. Topic List(100%)
13 | 3. Topic Detail(100%)
14 | 4. New Topic(100%)
15 | 5. Reply(100%)
16 | 6. HomePage(100%)
17 | 7. Profile(0%)
18 | 8. My Topics(0%)
19 | 9. My Favorites(0%)
20 | 10. Push Notification(80%)
21 | 11. Settings(0%)
22 |
23 | ## Installation
24 | It really need NodeJS & Ionic installed before you can play Our Project
25 |
26 | * NodeJS following:[Install NodeJS](https://nodejs.org/en/)
27 | * Ionic following:[Install Ionic](http://ionicframework.com/getting-started/)
28 |
29 | ```bash
30 | # Enter project root folder and input:
31 | $ npm install && bower install
32 |
33 | # auto-generater dist/ folder
34 | $ gulp useref
35 |
36 | # Adding iOS Platform
37 | $ ionic platform add ios
38 |
39 | # Adding Android Platform
40 | $ ionic platform add android
41 | ```
42 |
43 | ## Development
44 | Use `$ foreman start` or `$ ionic serve -w chrome -a` to start Server
45 | > cannot run foreman? run `$ gem install foreman` first.
46 |
47 | Use `bower install *** --save` install Bower components
48 | > If the dev server is running,Gulp will help you to adding all js dependency to `index.html`
49 | > If not, run `$ gulp` to make it.
50 |
51 | Use `npm install *** --save-dev` install npm modules
52 |
53 |
54 | ## Run in Chrome
55 |
56 | Open your Chrome and locate: http://localhost:8100/
57 | > Select device what you like
58 |
59 | ##### Screenshots
60 | 
61 |
62 | ## Run in Xcode
63 | Following these step, and you'll see it.
64 |
65 | ```bash
66 | # 1. Adding iOS Support
67 | $ ionic platform add ios
68 |
69 | # 2. Building
70 | $ ionic build ios
71 |
72 | # 3. run it in your simulator
73 | $ ionic emulate ios
74 | # another way, open Xcode first then run.
75 | $ open platforms/ios/Ruby China App.xcodeproj
76 | ```
77 |
78 | ##### Screenshots
79 | 
80 |
81 | ## Run in Android
82 | Following these step, and you'll see it.
83 |
84 | ```bash
85 | # 1. Adding Android Support
86 | $ ionic platform add android
87 |
88 | # 2. Download Android SDK & Simulator first
89 | > Ref on Mac[Android Studio Installation](http://developer.android.com/sdk/installing/index.html?pkg=studio)
90 |
91 | # 3. Everythings ok then build it
92 | $ ionic build android
93 |
94 | # 4. Open your simulator
95 | $ ionic emulate android
96 | ```
97 |
98 | ##### Screenshots
99 | 
100 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ruby-china-app",
3 | "private": "true",
4 | "devDependencies": {
5 | "ionic": "~1.2.1"
6 | },
7 | "dependencies": {
8 | "angular-moment": "~0.10.3",
9 | "angular-oauth2": "~3.0.1",
10 | "ng-file-upload": "~10.0.2",
11 | "robotodraft": "~1.1.0",
12 | "mdi": "~1.3.41",
13 | "lodash": "~3.10.1",
14 | "ngCordova": "~0.1.23-alpha"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Ruby China
4 |
5 | Official Ruby China Mobile App for iOS and Android.
6 |
7 |
8 | Ruby China Team
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/docs/images/doc_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/docs/images/doc_1.png
--------------------------------------------------------------------------------
/docs/images/doc_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/docs/images/doc_2.png
--------------------------------------------------------------------------------
/docs/images/doc_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/docs/images/doc_3.png
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | var gulp = require('gulp');
2 | var sh = require('shelljs');
3 | var bower = require('bower');
4 | var args = require('yargs').argv;
5 | var gulpif = require('gulp-if');
6 | var bower = require('./bower.json');
7 | var $ = require('gulp-load-plugins')({
8 | lazy: true
9 | });
10 |
11 | var paths = {
12 | lib: './www/lib',
13 | sass: ['./scss/**/*.scss'],
14 | src_js: ['./www/js/{,*/}*.module.js', './www/js/{,*/}*.js'],
15 | annotated_js: ['./www/annotated_js/{,*/}*.module.js', './www/annotated_js/{,*/}*.js'],
16 | templates: ['./www/templates/{,*/}*.html'],
17 | index: './www/index.html',
18 | useref: ['./www/*.html'],
19 | dist: ['./www/dist/**']
20 | };
21 |
22 | gulp.task('default', ['sass', 'wiredep']);
23 |
24 | gulp.task('sass', function(done) {
25 | gulp.src('./scss/style.scss')
26 | .pipe($.sass())
27 | .on('error', $.sass.logError)
28 | .pipe(gulp.dest('./www/css/'))
29 | .pipe($.minifyCss({
30 | keepSpecialComments: 0
31 | }))
32 | .pipe($.rename({
33 | extname: '.min.css'
34 | }))
35 | .pipe(gulp.dest('./www/css/'))
36 | .on('end', done);
37 | });
38 |
39 | gulp.task('watch', function() {
40 | gulp.watch(paths.sass, ['sass']);
41 | gulp.watch(paths.templates, ['templateCache']);
42 | gulp.watch(paths.src_js, ['wiredep']);
43 | });
44 |
45 | gulp.task('install', ['git-check'], function() {
46 | return bower.commands.install()
47 | .on('log', function(data) {
48 | gutil.log('bower', gutil.colors.cyan(data.id), data.message);
49 | });
50 | });
51 |
52 | gulp.task('git-check', function(done) {
53 | if (!sh.which('git')) {
54 | console.log(
55 | ' ' + gutil.colors.red('Git is not installed.'),
56 | '\n Git, the version control system, is required to download Ionic.',
57 | '\n Download git here:', gutil.colors.cyan('http://git-scm.com/downloads') + '.',
58 | '\n Once git is installed, run \'' + gutil.colors.cyan('gulp install') + '\' again.'
59 | );
60 | process.exit(1);
61 | }
62 | done();
63 | });
64 |
65 | gulp.task('templateCache', function() {
66 | return gulp.src(paths.templates)
67 | .pipe($.angularTemplatecache({
68 | standalone: true
69 | }))
70 | .pipe(gulp.dest('./www/annotated_js'));
71 | });
72 |
73 | gulp.task('clean-dist', function() {
74 | return gulp
75 | .src(paths.dist, {
76 | read: false
77 | })
78 | .pipe($.rimraf());
79 | });
80 |
81 | // 增加依赖注入
82 | gulp.task('ngAnnotate', ['templateCache'], function() {
83 | return gulp.src(paths.src_js)
84 | .pipe($.ngAnnotate({
85 | single_quotes: true
86 | }))
87 | .pipe(gulp.dest('./www/annotated_js'));
88 | });
89 |
90 | // 将所有JS及CSS引用添加到index.html
91 | gulp.task('wiredep', ['ngAnnotate'], function() {
92 | var options = {
93 | bowerJson: bower,
94 | directory: paths.lib,
95 | ignorePath: '../..',
96 | devDependencies: true
97 | };
98 | var wiredep = require('wiredep').stream;
99 |
100 | return gulp
101 | .src(paths.index)
102 | .pipe(wiredep(options))
103 | .pipe($.inject(gulp.src(paths.annotated_js, {
104 | read: false
105 | }), {
106 | relative: true
107 | }))
108 | .pipe(gulp.dest('./www'));
109 | });
110 |
111 |
112 | gulp.task('useref', ['clean-dist', 'sass', 'wiredep'], function() {
113 | return gulp.src(paths.useref)
114 | .pipe($.useref())
115 | .pipe(gulpif('*.js', $.uglify()))
116 | .pipe(gulpif('*.css', $.minifyCss()))
117 | .pipe(gulp.dest('./www/dist'));
118 | });
119 |
--------------------------------------------------------------------------------
/hooks/README.md:
--------------------------------------------------------------------------------
1 |
21 | # Cordova Hooks
22 |
23 | This directory may contain scripts used to customize cordova commands. This
24 | directory used to exist at `.cordova/hooks`, but has now been moved to the
25 | project root. Any scripts you add to these directories will be executed before
26 | and after the commands corresponding to the directory name. Useful for
27 | integrating your own build systems or integrating with version control systems.
28 |
29 | __Remember__: Make your scripts executable.
30 |
31 | ## Hook Directories
32 | The following subdirectories will be used for hooks:
33 |
34 | after_build/
35 | after_compile/
36 | after_docs/
37 | after_emulate/
38 | after_platform_add/
39 | after_platform_rm/
40 | after_platform_ls/
41 | after_plugin_add/
42 | after_plugin_ls/
43 | after_plugin_rm/
44 | after_plugin_search/
45 | after_prepare/
46 | after_run/
47 | after_serve/
48 | before_build/
49 | before_compile/
50 | before_docs/
51 | before_emulate/
52 | before_platform_add/
53 | before_platform_rm/
54 | before_platform_ls/
55 | before_plugin_add/
56 | before_plugin_ls/
57 | before_plugin_rm/
58 | before_plugin_search/
59 | before_prepare/
60 | before_run/
61 | before_serve/
62 | pre_package/ <-- Windows 8 and Windows Phone only.
63 |
64 | ## Script Interface
65 |
66 | All scripts are run from the project's root directory and have the root directory passes as the first argument. All other options are passed to the script using environment variables:
67 |
68 | * CORDOVA_VERSION - The version of the Cordova-CLI.
69 | * CORDOVA_PLATFORMS - Comma separated list of platforms that the command applies to (e.g.: android, ios).
70 | * CORDOVA_PLUGINS - Comma separated list of plugin IDs that the command applies to (e.g.: org.apache.cordova.file, org.apache.cordova.file-transfer)
71 | * CORDOVA_HOOK - Path to the hook that is being executed.
72 | * CORDOVA_CMDLINE - The exact command-line arguments passed to cordova (e.g.: cordova run ios --emulate)
73 |
74 | If a script returns a non-zero exit code, then the parent cordova command will be aborted.
75 |
76 |
77 | ## Writing hooks
78 |
79 | We highly recommend writting your hooks using Node.js so that they are
80 | cross-platform. Some good examples are shown here:
81 |
82 | [http://devgirl.org/2013/11/12/three-hooks-your-cordovaphonegap-project-needs/](http://devgirl.org/2013/11/12/three-hooks-your-cordovaphonegap-project-needs/)
83 |
84 |
--------------------------------------------------------------------------------
/hooks/after_prepare/010_add_platform_class.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | // Add Platform Class
4 | // v1.0
5 | // Automatically adds the platform class to the body tag
6 | // after the `prepare` command. By placing the platform CSS classes
7 | // directly in the HTML built for the platform, it speeds up
8 | // rendering the correct layout/style for the specific platform
9 | // instead of waiting for the JS to figure out the correct classes.
10 |
11 | var fs = require('fs');
12 | var path = require('path');
13 |
14 | var rootdir = process.argv[2];
15 |
16 | function addPlatformBodyTag(indexPath, platform) {
17 | // add the platform class to the body tag
18 | try {
19 | var platformClass = 'platform-' + platform;
20 | var cordovaClass = 'platform-cordova platform-webview';
21 |
22 | var html = fs.readFileSync(indexPath, 'utf8');
23 |
24 | var bodyTag = findBodyTag(html);
25 | if(!bodyTag) return; // no opening body tag, something's wrong
26 |
27 | if(bodyTag.indexOf(platformClass) > -1) return; // already added
28 |
29 | var newBodyTag = bodyTag;
30 |
31 | var classAttr = findClassAttr(bodyTag);
32 | if(classAttr) {
33 | // body tag has existing class attribute, add the classname
34 | var endingQuote = classAttr.substring(classAttr.length-1);
35 | var newClassAttr = classAttr.substring(0, classAttr.length-1);
36 | newClassAttr += ' ' + platformClass + ' ' + cordovaClass + endingQuote;
37 | newBodyTag = bodyTag.replace(classAttr, newClassAttr);
38 |
39 | } else {
40 | // add class attribute to the body tag
41 | newBodyTag = bodyTag.replace('>', ' class="' + platformClass + ' ' + cordovaClass + '">');
42 | }
43 |
44 | html = html.replace(bodyTag, newBodyTag);
45 |
46 | fs.writeFileSync(indexPath, html, 'utf8');
47 |
48 | process.stdout.write('add to body class: ' + platformClass + '\n');
49 | } catch(e) {
50 | process.stdout.write(e);
51 | }
52 | }
53 |
54 | function findBodyTag(html) {
55 | // get the body tag
56 | try{
57 | return html.match(/
])(.*?)>/gi)[0];
58 | }catch(e){}
59 | }
60 |
61 | function findClassAttr(bodyTag) {
62 | // get the body tag's class attribute
63 | try{
64 | return bodyTag.match(/ class=["|'](.*?)["|']/gi)[0];
65 | }catch(e){}
66 | }
67 |
68 | if (rootdir) {
69 |
70 | // go through each of the platform directories that have been prepared
71 | var platforms = (process.env.CORDOVA_PLATFORMS ? process.env.CORDOVA_PLATFORMS.split(',') : []);
72 |
73 | for(var x=0; x 0) {
43 | process.exit(1);
44 | }
45 | });
46 | });
47 | }
48 |
49 | function lintFile(file, callback) {
50 | console.log("Linting " + file);
51 | fs.readFile(file, function(err, data) {
52 | if (err) {
53 | console.log('Error: ' + err);
54 | return;
55 | }
56 | if (jshint(data.toString())) {
57 | console.log('File ' + file + ' has no errors.');
58 | console.log('-----------------------------------------');
59 | callback(false);
60 | } else {
61 | console.log('Errors in file ' + file);
62 | var out = jshint.data(),
63 | errors = out.errors;
64 | for (var j = 0; j < errors.length; j++) {
65 | console.log(errors[j].line + ':' + errors[j].character + ' -> ' + errors[j].reason + ' -> ' +
66 | errors[j].evidence);
67 | }
68 | console.log('-----------------------------------------');
69 | callback(true);
70 | }
71 | });
72 | }
73 |
--------------------------------------------------------------------------------
/ionic.project:
--------------------------------------------------------------------------------
1 | {
2 | "name": "RubyChina App",
3 | "app_id": "61fdad52",
4 | "gulpStartupTasks": [
5 | "wiredep",
6 | "watch",
7 | "sass"
8 | ],
9 | "watchPatterns": [
10 | "www/**/*",
11 | "!www/lib/**/*"
12 | ]
13 | }
14 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ruby-china-app",
3 | "description": "Official Ruby China Mobile App",
4 | "dependencies": {},
5 | "devDependencies": {
6 | "async": "^1.5.0",
7 | "bower": "^1.3.3",
8 | "clean-css": "^3.4.8",
9 | "gulp": "^3.5.6",
10 | "gulp-angular-templatecache": "^1.8.0",
11 | "gulp-concat": "^2.2.0",
12 | "gulp-if": "^2.0.0",
13 | "gulp-inject": "^3.0.0",
14 | "gulp-load-plugins": "^1.1.0",
15 | "gulp-minify-css": "^1.2.3",
16 | "gulp-ng-annotate": "^1.1.0",
17 | "gulp-print": "^2.0.1",
18 | "gulp-rename": "^1.2.0",
19 | "gulp-rimraf": "^0.2.0",
20 | "gulp-sass": "^2.0.4",
21 | "gulp-uglify": "^1.5.1",
22 | "gulp-useref": "^3.0.0",
23 | "gulp-util": "^3.0.7",
24 | "ionic": "1.7.14",
25 | "jshint": "^2.8.0",
26 | "jshint-stylish": "^2.1.0",
27 | "mv": "^2.1.1",
28 | "ng-annotate": "^1.0.2",
29 | "shelljs": "^0.5.3",
30 | "uglify-js": "^2.6.1",
31 | "wiredep": "3.0.0",
32 | "yargs": "^3.30.0"
33 | },
34 | "cordovaPlugins": [
35 | "cordova-plugin-safariviewcontroller",
36 | "cordova-plugin-app-version",
37 | "cordova-plugin-statusbar",
38 | "cordova-plugin-device",
39 | "cordova-plugin-whitelist",
40 | {
41 | "locator": "https://github.com/phonegap-build/PushPlugin",
42 | "id": "phonegap-plugin-push",
43 | "tag": "2.5.0"
44 | }
45 | ],
46 | "cordovaPlatforms": [
47 | "ios"
48 | ]
49 | }
50 |
--------------------------------------------------------------------------------
/platforms/ios/.gitignore:
--------------------------------------------------------------------------------
1 | *.mode1v3
2 | *.perspectivev3
3 | *.pbxuser
4 | .DS_Store
5 | build/
6 |
--------------------------------------------------------------------------------
/platforms/ios/Ruby China.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/platforms/ios/Ruby China.xcodeproj/project.xcworkspace/xcuserdata/jason.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/platforms/ios/Ruby China.xcodeproj/project.xcworkspace/xcuserdata/jason.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/platforms/ios/Ruby China.xcodeproj/xcuserdata/jason.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
8 |
20 |
21 |
22 |
24 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/platforms/ios/Ruby China.xcodeproj/xcuserdata/jason.xcuserdatad/xcschemes/Ruby China.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
54 |
56 |
62 |
63 |
64 |
65 |
66 |
67 |
73 |
75 |
81 |
82 |
83 |
84 |
86 |
87 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/platforms/ios/Ruby China.xcodeproj/xcuserdata/jason.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | Ruby China.xcscheme
8 |
9 | orderHint
10 | 0
11 |
12 |
13 | SuppressBuildableAutocreation
14 |
15 | 1D6058900D05DD3D006BFB54
16 |
17 | primary
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/platforms/ios/Ruby China/.gitignore:
--------------------------------------------------------------------------------
1 | *.mode1v3
2 | *.perspectivev3
3 | *.pbxuser
4 | .DS_Store
5 | build/
6 |
--------------------------------------------------------------------------------
/platforms/ios/Ruby China/Bridging-Header.h:
--------------------------------------------------------------------------------
1 | /*
2 | Licensed to the Apache Software Foundation (ASF) under one
3 | or more contributor license agreements. See the NOTICE file
4 | distributed with this work for additional information
5 | regarding copyright ownership. The ASF licenses this file
6 | to you under the Apache License, Version 2.0 (the
7 | "License"); you may not use this file except in compliance
8 | with the License. You may obtain a copy of the License at
9 | http://www.apache.org/licenses/LICENSE-2.0
10 | Unless required by applicable law or agreed to in writing,
11 | software distributed under the License is distributed on an
12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
13 | KIND, either express or implied. See the License for the
14 | specific language governing permissions and limitations
15 | under the License.
16 | */
17 | //
18 | // Bridging-Header.h
19 | // __PROJECT_NAME__
20 | //
21 | // Created by ___FULLUSERNAME___ on ___DATE___.
22 | // Copyright ___ORGANIZATIONNAME___ ___YEAR___. All rights reserved.
23 | //
24 | //
25 | // Use this file to import your target's public headers that you would like to expose to Swift.
26 | //
27 |
28 | #import
29 |
--------------------------------------------------------------------------------
/platforms/ios/Ruby China/Classes/AppDelegate.h:
--------------------------------------------------------------------------------
1 | /*
2 | Licensed to the Apache Software Foundation (ASF) under one
3 | or more contributor license agreements. See the NOTICE file
4 | distributed with this work for additional information
5 | regarding copyright ownership. The ASF licenses this file
6 | to you under the Apache License, Version 2.0 (the
7 | "License"); you may not use this file except in compliance
8 | with the License. You may obtain a copy of the License at
9 |
10 | http://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing,
13 | software distributed under the License is distributed on an
14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | KIND, either express or implied. See the License for the
16 | specific language governing permissions and limitations
17 | under the License.
18 | */
19 |
20 | //
21 | // AppDelegate.h
22 | // Ruby China
23 | //
24 | // Created by ___FULLUSERNAME___ on ___DATE___.
25 | // Copyright ___ORGANIZATIONNAME___ ___YEAR___. All rights reserved.
26 | //
27 |
28 | #import
29 | #import
30 |
31 | @interface AppDelegate : CDVAppDelegate {}
32 |
33 | @end
34 |
--------------------------------------------------------------------------------
/platforms/ios/Ruby China/Classes/AppDelegate.m:
--------------------------------------------------------------------------------
1 | /*
2 | Licensed to the Apache Software Foundation (ASF) under one
3 | or more contributor license agreements. See the NOTICE file
4 | distributed with this work for additional information
5 | regarding copyright ownership. The ASF licenses this file
6 | to you under the Apache License, Version 2.0 (the
7 | "License"); you may not use this file except in compliance
8 | with the License. You may obtain a copy of the License at
9 |
10 | http://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing,
13 | software distributed under the License is distributed on an
14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | KIND, either express or implied. See the License for the
16 | specific language governing permissions and limitations
17 | under the License.
18 | */
19 |
20 | //
21 | // AppDelegate.m
22 | // Ruby China
23 | //
24 | // Created by ___FULLUSERNAME___ on ___DATE___.
25 | // Copyright ___ORGANIZATIONNAME___ ___YEAR___. All rights reserved.
26 | //
27 |
28 | #import "AppDelegate.h"
29 | #import "MainViewController.h"
30 |
31 | @implementation AppDelegate
32 |
33 | - (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
34 | {
35 | self.viewController = [[MainViewController alloc] init];
36 | return [super application:application didFinishLaunchingWithOptions:launchOptions];
37 | }
38 |
39 | @end
40 |
--------------------------------------------------------------------------------
/platforms/ios/Ruby China/Classes/MainViewController.h:
--------------------------------------------------------------------------------
1 | /*
2 | Licensed to the Apache Software Foundation (ASF) under one
3 | or more contributor license agreements. See the NOTICE file
4 | distributed with this work for additional information
5 | regarding copyright ownership. The ASF licenses this file
6 | to you under the Apache License, Version 2.0 (the
7 | "License"); you may not use this file except in compliance
8 | with the License. You may obtain a copy of the License at
9 |
10 | http://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing,
13 | software distributed under the License is distributed on an
14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | KIND, either express or implied. See the License for the
16 | specific language governing permissions and limitations
17 | under the License.
18 | */
19 |
20 | //
21 | // MainViewController.h
22 | // Ruby China
23 | //
24 | // Created by ___FULLUSERNAME___ on ___DATE___.
25 | // Copyright ___ORGANIZATIONNAME___ ___YEAR___. All rights reserved.
26 | //
27 |
28 | #import
29 | #import
30 | #import
31 |
32 | @interface MainViewController : CDVViewController
33 |
34 | @end
35 |
36 | @interface MainCommandDelegate : CDVCommandDelegateImpl
37 | @end
38 |
39 | @interface MainCommandQueue : CDVCommandQueue
40 | @end
41 |
--------------------------------------------------------------------------------
/platforms/ios/Ruby China/Classes/MainViewController.m:
--------------------------------------------------------------------------------
1 | /*
2 | Licensed to the Apache Software Foundation (ASF) under one
3 | or more contributor license agreements. See the NOTICE file
4 | distributed with this work for additional information
5 | regarding copyright ownership. The ASF licenses this file
6 | to you under the Apache License, Version 2.0 (the
7 | "License"); you may not use this file except in compliance
8 | with the License. You may obtain a copy of the License at
9 |
10 | http://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing,
13 | software distributed under the License is distributed on an
14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | KIND, either express or implied. See the License for the
16 | specific language governing permissions and limitations
17 | under the License.
18 | */
19 |
20 | //
21 | // MainViewController.h
22 | // Ruby China
23 | //
24 | // Created by ___FULLUSERNAME___ on ___DATE___.
25 | // Copyright ___ORGANIZATIONNAME___ ___YEAR___. All rights reserved.
26 | //
27 |
28 | #import "MainViewController.h"
29 |
30 | @implementation MainViewController
31 |
32 | - (id)initWithNibName:(NSString*)nibNameOrNil bundle:(NSBundle*)nibBundleOrNil
33 | {
34 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
35 | if (self) {
36 | // Uncomment to override the CDVCommandDelegateImpl used
37 | // _commandDelegate = [[MainCommandDelegate alloc] initWithViewController:self];
38 | // Uncomment to override the CDVCommandQueue used
39 | // _commandQueue = [[MainCommandQueue alloc] initWithViewController:self];
40 | }
41 | return self;
42 | }
43 |
44 | - (id)init
45 | {
46 | self = [super init];
47 | if (self) {
48 | // Uncomment to override the CDVCommandDelegateImpl used
49 | // _commandDelegate = [[MainCommandDelegate alloc] initWithViewController:self];
50 | // Uncomment to override the CDVCommandQueue used
51 | // _commandQueue = [[MainCommandQueue alloc] initWithViewController:self];
52 | }
53 | return self;
54 | }
55 |
56 | - (void)didReceiveMemoryWarning
57 | {
58 | // Releases the view if it doesn't have a superview.
59 | [super didReceiveMemoryWarning];
60 |
61 | // Release any cached data, images, etc that aren't in use.
62 | }
63 |
64 | #pragma mark View lifecycle
65 |
66 | - (void)viewWillAppear:(BOOL)animated
67 | {
68 | // View defaults to full size. If you want to customize the view's size, or its subviews (e.g. webView),
69 | // you can do so here.
70 |
71 | [super viewWillAppear:animated];
72 | }
73 |
74 | - (void)viewDidLoad
75 | {
76 | [super viewDidLoad];
77 | // Do any additional setup after loading the view from its nib.
78 | }
79 |
80 | - (void)viewDidUnload
81 | {
82 | [super viewDidUnload];
83 | // Release any retained subviews of the main view.
84 | // e.g. self.myOutlet = nil;
85 | }
86 |
87 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
88 | {
89 | // Return YES for supported orientations
90 | return [super shouldAutorotateToInterfaceOrientation:interfaceOrientation];
91 | }
92 |
93 | /* Comment out the block below to over-ride */
94 |
95 | /*
96 | - (UIWebView*) newCordovaViewWithFrame:(CGRect)bounds
97 | {
98 | return[super newCordovaViewWithFrame:bounds];
99 | }
100 | */
101 |
102 | @end
103 |
104 | @implementation MainCommandDelegate
105 |
106 | /* To override the methods, uncomment the line in the init function(s)
107 | in MainViewController.m
108 | */
109 |
110 | #pragma mark CDVCommandDelegate implementation
111 |
112 | - (id)getCommandInstance:(NSString*)className
113 | {
114 | return [super getCommandInstance:className];
115 | }
116 |
117 | - (NSString*)pathForResource:(NSString*)resourcepath
118 | {
119 | return [super pathForResource:resourcepath];
120 | }
121 |
122 | @end
123 |
124 | @implementation MainCommandQueue
125 |
126 | /* To override, uncomment the line in the init function(s)
127 | in MainViewController.m
128 | */
129 | - (BOOL)execute:(CDVInvokedUrlCommand*)command
130 | {
131 | return [super execute:command];
132 | }
133 |
134 | @end
135 |
--------------------------------------------------------------------------------
/platforms/ios/Ruby China/Classes/MainViewController.xib:
--------------------------------------------------------------------------------
1 |
2 |
22 |
23 |
24 | 1280
25 | 11C25
26 | 1919
27 | 1138.11
28 | 566.00
29 |
33 |
34 | IBProxyObject
35 | IBUIView
36 |
37 |
38 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin
39 |
40 |
44 |
45 |
49 |
53 |
69 |
70 |
71 |
72 |
73 |
74 | view
75 |
76 |
77 |
78 | 3
79 |
80 |
81 |
82 |
83 |
84 | 0
85 |
86 |
87 |
88 |
89 |
90 | 1
91 |
92 |
93 |
94 |
95 | -1
96 |
97 |
98 | File's Owner
99 |
100 |
101 | -2
102 |
103 |
104 |
105 |
106 |
107 |
108 | MainViewController
109 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin
110 | UIResponder
111 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin
112 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin
113 |
114 |
115 |
116 |
117 |
118 | 3
119 |
120 |
121 |
122 |
123 | MainViewController
124 | UIViewController
125 |
126 | IBProjectSource
127 | ./Classes/MainViewController.h
128 |
129 |
130 |
131 |
132 | 0
133 | IBCocoaTouchFramework
134 | YES
135 | 3
136 | 916
137 |
138 |
139 |
--------------------------------------------------------------------------------
/platforms/ios/Ruby China/Images.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "29x29",
6 | "filename" : "icon-small.png",
7 | "scale" : "1x"
8 | },
9 | {
10 | "idiom" : "iphone",
11 | "size" : "29x29",
12 | "filename" : "icon-small@2x.png",
13 | "scale" : "2x"
14 | },
15 | {
16 | "idiom" : "iphone",
17 | "size" : "29x29",
18 | "filename" : "icon-small@3x.png",
19 | "scale" : "3x"
20 | },
21 | {
22 | "idiom" : "iphone",
23 | "size" : "40x40",
24 | "filename" : "icon-40@2x.png",
25 | "scale" : "2x"
26 | },
27 | {
28 | "idiom" : "iphone",
29 | "size" : "40x40",
30 | "filename" : "icon-60@2x.png",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "size" : "57x57",
36 | "filename" : "icon.png",
37 | "scale" : "1x"
38 | },
39 | {
40 | "idiom" : "iphone",
41 | "size" : "57x57",
42 | "filename" : "icon@2x.png",
43 | "scale" : "2x"
44 | },
45 | {
46 | "idiom" : "iphone",
47 | "size" : "60x60",
48 | "filename" : "icon-60@2x.png",
49 | "scale" : "2x"
50 | },
51 | {
52 | "idiom" : "iphone",
53 | "size" : "60x60",
54 | "filename" : "icon-60@3x.png",
55 | "scale" : "3x"
56 | },
57 | {
58 | "idiom" : "ipad",
59 | "size" : "29x29",
60 | "filename" : "icon-small.png",
61 | "scale" : "1x"
62 | },
63 | {
64 | "idiom" : "ipad",
65 | "size" : "29x29",
66 | "filename" : "icon-small@2x.png",
67 | "scale" : "2x"
68 | },
69 | {
70 | "idiom" : "ipad",
71 | "size" : "40x40",
72 | "filename" : "icon-40.png",
73 | "scale" : "1x"
74 | },
75 | {
76 | "idiom" : "ipad",
77 | "size" : "40x40",
78 | "filename" : "icon-40@2x.png",
79 | "scale" : "2x"
80 | },
81 | {
82 | "idiom" : "ipad",
83 | "size" : "50x50",
84 | "filename" : "icon-50.png",
85 | "scale" : "1x"
86 | },
87 | {
88 | "idiom" : "ipad",
89 | "size" : "50x50",
90 | "filename" : "icon-50@2x.png",
91 | "scale" : "2x"
92 | },
93 | {
94 | "idiom" : "ipad",
95 | "size" : "72x72",
96 | "filename" : "icon-72.png",
97 | "scale" : "1x"
98 | },
99 | {
100 | "idiom" : "ipad",
101 | "size" : "72x72",
102 | "filename" : "icon-72@2x.png",
103 | "scale" : "2x"
104 | },
105 | {
106 | "idiom" : "ipad",
107 | "size" : "76x76",
108 | "filename" : "icon-76.png",
109 | "scale" : "1x"
110 | },
111 | {
112 | "idiom" : "ipad",
113 | "size" : "76x76",
114 | "filename" : "icon-76@2x.png",
115 | "scale" : "2x"
116 | },
117 | {
118 | "idiom" : "ipad",
119 | "size" : "83.5x83.5",
120 | "filename" : "icon-83.5@2x.png",
121 | "scale" : "2x"
122 | },
123 | {
124 | "size" : "24x24",
125 | "idiom" : "watch",
126 | "scale" : "2x",
127 | "role" : "notificationCenter",
128 | "subtype" : "38mm"
129 | },
130 | {
131 | "size" : "27.5x27.5",
132 | "idiom" : "watch",
133 | "scale" : "2x",
134 | "role" : "notificationCenter",
135 | "subtype" : "42mm"
136 | },
137 | {
138 | "size" : "29x29",
139 | "idiom" : "watch",
140 | "role" : "companionSettings",
141 | "scale" : "2x"
142 | },
143 | {
144 | "size" : "29x29",
145 | "idiom" : "watch",
146 | "role" : "companionSettings",
147 | "scale" : "3x"
148 | },
149 | {
150 | "size" : "40x40",
151 | "idiom" : "watch",
152 | "scale" : "2x",
153 | "role" : "appLauncher",
154 | "subtype" : "38mm"
155 | },
156 | {
157 | "size" : "44x44",
158 | "idiom" : "watch",
159 | "scale" : "2x",
160 | "role" : "longLook",
161 | "subtype" : "42mm"
162 | },
163 | {
164 | "size" : "86x86",
165 | "idiom" : "watch",
166 | "scale" : "2x",
167 | "role" : "quickLook",
168 | "subtype" : "38mm"
169 | },
170 | {
171 | "size" : "98x98",
172 | "idiom" : "watch",
173 | "scale" : "2x",
174 | "role" : "quickLook",
175 | "subtype" : "42mm"
176 | }
177 | ],
178 | "info" : {
179 | "version" : 1,
180 | "author" : "xcode"
181 | }
182 | }
--------------------------------------------------------------------------------
/platforms/ios/Ruby China/Images.xcassets/AppIcon.appiconset/icon-40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/platforms/ios/Ruby China/Images.xcassets/AppIcon.appiconset/icon-40.png
--------------------------------------------------------------------------------
/platforms/ios/Ruby China/Images.xcassets/AppIcon.appiconset/icon-40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/platforms/ios/Ruby China/Images.xcassets/AppIcon.appiconset/icon-40@2x.png
--------------------------------------------------------------------------------
/platforms/ios/Ruby China/Images.xcassets/AppIcon.appiconset/icon-50.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/platforms/ios/Ruby China/Images.xcassets/AppIcon.appiconset/icon-50.png
--------------------------------------------------------------------------------
/platforms/ios/Ruby China/Images.xcassets/AppIcon.appiconset/icon-50@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/platforms/ios/Ruby China/Images.xcassets/AppIcon.appiconset/icon-50@2x.png
--------------------------------------------------------------------------------
/platforms/ios/Ruby China/Images.xcassets/AppIcon.appiconset/icon-60.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/platforms/ios/Ruby China/Images.xcassets/AppIcon.appiconset/icon-60.png
--------------------------------------------------------------------------------
/platforms/ios/Ruby China/Images.xcassets/AppIcon.appiconset/icon-60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/platforms/ios/Ruby China/Images.xcassets/AppIcon.appiconset/icon-60@2x.png
--------------------------------------------------------------------------------
/platforms/ios/Ruby China/Images.xcassets/AppIcon.appiconset/icon-60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/platforms/ios/Ruby China/Images.xcassets/AppIcon.appiconset/icon-60@3x.png
--------------------------------------------------------------------------------
/platforms/ios/Ruby China/Images.xcassets/AppIcon.appiconset/icon-72.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/platforms/ios/Ruby China/Images.xcassets/AppIcon.appiconset/icon-72.png
--------------------------------------------------------------------------------
/platforms/ios/Ruby China/Images.xcassets/AppIcon.appiconset/icon-72@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/platforms/ios/Ruby China/Images.xcassets/AppIcon.appiconset/icon-72@2x.png
--------------------------------------------------------------------------------
/platforms/ios/Ruby China/Images.xcassets/AppIcon.appiconset/icon-76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/platforms/ios/Ruby China/Images.xcassets/AppIcon.appiconset/icon-76.png
--------------------------------------------------------------------------------
/platforms/ios/Ruby China/Images.xcassets/AppIcon.appiconset/icon-76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/platforms/ios/Ruby China/Images.xcassets/AppIcon.appiconset/icon-76@2x.png
--------------------------------------------------------------------------------
/platforms/ios/Ruby China/Images.xcassets/AppIcon.appiconset/icon-83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/platforms/ios/Ruby China/Images.xcassets/AppIcon.appiconset/icon-83.5@2x.png
--------------------------------------------------------------------------------
/platforms/ios/Ruby China/Images.xcassets/AppIcon.appiconset/icon-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/platforms/ios/Ruby China/Images.xcassets/AppIcon.appiconset/icon-small.png
--------------------------------------------------------------------------------
/platforms/ios/Ruby China/Images.xcassets/AppIcon.appiconset/icon-small@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/platforms/ios/Ruby China/Images.xcassets/AppIcon.appiconset/icon-small@2x.png
--------------------------------------------------------------------------------
/platforms/ios/Ruby China/Images.xcassets/AppIcon.appiconset/icon-small@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/platforms/ios/Ruby China/Images.xcassets/AppIcon.appiconset/icon-small@3x.png
--------------------------------------------------------------------------------
/platforms/ios/Ruby China/Images.xcassets/AppIcon.appiconset/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/platforms/ios/Ruby China/Images.xcassets/AppIcon.appiconset/icon.png
--------------------------------------------------------------------------------
/platforms/ios/Ruby China/Images.xcassets/AppIcon.appiconset/icon@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/platforms/ios/Ruby China/Images.xcassets/AppIcon.appiconset/icon@2x.png
--------------------------------------------------------------------------------
/platforms/ios/Ruby China/Images.xcassets/LaunchImage.launchimage/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "extent" : "full-screen",
5 | "idiom" : "iphone",
6 | "subtype" : "736h",
7 | "filename" : "Default-736h.png",
8 | "minimum-system-version" : "8.0",
9 | "orientation" : "portrait",
10 | "scale" : "3x"
11 | },
12 | {
13 | "extent" : "full-screen",
14 | "idiom" : "iphone",
15 | "subtype" : "736h",
16 | "filename" : "Default-Landscape-736h.png",
17 | "minimum-system-version" : "8.0",
18 | "orientation" : "landscape",
19 | "scale" : "3x"
20 | },
21 | {
22 | "extent" : "full-screen",
23 | "idiom" : "iphone",
24 | "subtype" : "667h",
25 | "filename" : "Default-667h.png",
26 | "minimum-system-version" : "8.0",
27 | "orientation" : "portrait",
28 | "scale" : "2x"
29 | },
30 | {
31 | "orientation" : "portrait",
32 | "idiom" : "iphone",
33 | "filename" : "Default@2x~iphone.png",
34 | "extent" : "full-screen",
35 | "minimum-system-version" : "7.0",
36 | "scale" : "2x"
37 | },
38 | {
39 | "extent" : "full-screen",
40 | "idiom" : "iphone",
41 | "subtype" : "retina4",
42 | "filename" : "Default-568h@2x~iphone.png",
43 | "minimum-system-version" : "7.0",
44 | "orientation" : "portrait",
45 | "scale" : "2x"
46 | },
47 | {
48 | "orientation" : "portrait",
49 | "idiom" : "ipad",
50 | "filename" : "Default-Portrait~ipad.png",
51 | "extent" : "full-screen",
52 | "minimum-system-version" : "7.0",
53 | "scale" : "1x"
54 | },
55 | {
56 | "orientation" : "landscape",
57 | "idiom" : "ipad",
58 | "filename" : "Default-Landscape~ipad.png",
59 | "extent" : "full-screen",
60 | "minimum-system-version" : "7.0",
61 | "scale" : "1x"
62 | },
63 | {
64 | "orientation" : "portrait",
65 | "idiom" : "ipad",
66 | "filename" : "Default-Portrait@2x~ipad.png",
67 | "extent" : "full-screen",
68 | "minimum-system-version" : "7.0",
69 | "scale" : "2x"
70 | },
71 | {
72 | "orientation" : "landscape",
73 | "idiom" : "ipad",
74 | "filename" : "Default-Landscape@2x~ipad.png",
75 | "extent" : "full-screen",
76 | "minimum-system-version" : "7.0",
77 | "scale" : "2x"
78 | },
79 | {
80 | "orientation" : "portrait",
81 | "idiom" : "iphone",
82 | "filename" : "Default~iphone.png",
83 | "extent" : "full-screen",
84 | "scale" : "1x"
85 | },
86 | {
87 | "orientation" : "portrait",
88 | "idiom" : "iphone",
89 | "filename" : "Default@2x~iphone.png",
90 | "extent" : "full-screen",
91 | "scale" : "2x"
92 | },
93 | {
94 | "orientation" : "portrait",
95 | "idiom" : "iphone",
96 | "filename" : "Default-568h@2x~iphone.png",
97 | "extent" : "full-screen",
98 | "subtype" : "retina4",
99 | "scale" : "2x"
100 | },
101 | {
102 | "orientation" : "portrait",
103 | "idiom" : "ipad",
104 | "extent" : "to-status-bar",
105 | "scale" : "1x"
106 | },
107 | {
108 | "orientation" : "portrait",
109 | "idiom" : "ipad",
110 | "filename" : "Default-Portrait~ipad.png",
111 | "extent" : "full-screen",
112 | "scale" : "1x"
113 | },
114 | {
115 | "orientation" : "landscape",
116 | "idiom" : "ipad",
117 | "extent" : "to-status-bar",
118 | "scale" : "1x"
119 | },
120 | {
121 | "orientation" : "landscape",
122 | "idiom" : "ipad",
123 | "extent" : "full-screen",
124 | "scale" : "1x"
125 | },
126 | {
127 | "orientation" : "portrait",
128 | "idiom" : "ipad",
129 | "extent" : "to-status-bar",
130 | "scale" : "2x"
131 | },
132 | {
133 | "orientation" : "portrait",
134 | "idiom" : "ipad",
135 | "filename" : "Default-Portrait@2x~ipad.png",
136 | "extent" : "full-screen",
137 | "scale" : "2x"
138 | },
139 | {
140 | "orientation" : "landscape",
141 | "idiom" : "ipad",
142 | "extent" : "to-status-bar",
143 | "scale" : "2x"
144 | },
145 | {
146 | "orientation" : "landscape",
147 | "idiom" : "ipad",
148 | "extent" : "full-screen",
149 | "scale" : "2x"
150 | }
151 | ],
152 | "info" : {
153 | "version" : 1,
154 | "author" : "xcode"
155 | }
156 | }
--------------------------------------------------------------------------------
/platforms/ios/Ruby China/Images.xcassets/LaunchImage.launchimage/Default-568h@2x~iphone.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/platforms/ios/Ruby China/Images.xcassets/LaunchImage.launchimage/Default-568h@2x~iphone.png
--------------------------------------------------------------------------------
/platforms/ios/Ruby China/Images.xcassets/LaunchImage.launchimage/Default-667h.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/platforms/ios/Ruby China/Images.xcassets/LaunchImage.launchimage/Default-667h.png
--------------------------------------------------------------------------------
/platforms/ios/Ruby China/Images.xcassets/LaunchImage.launchimage/Default-736h.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/platforms/ios/Ruby China/Images.xcassets/LaunchImage.launchimage/Default-736h.png
--------------------------------------------------------------------------------
/platforms/ios/Ruby China/Images.xcassets/LaunchImage.launchimage/Default-Landscape-736h.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/platforms/ios/Ruby China/Images.xcassets/LaunchImage.launchimage/Default-Landscape-736h.png
--------------------------------------------------------------------------------
/platforms/ios/Ruby China/Images.xcassets/LaunchImage.launchimage/Default-Landscape@2x~ipad.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/platforms/ios/Ruby China/Images.xcassets/LaunchImage.launchimage/Default-Landscape@2x~ipad.png
--------------------------------------------------------------------------------
/platforms/ios/Ruby China/Images.xcassets/LaunchImage.launchimage/Default-Landscape~ipad.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/platforms/ios/Ruby China/Images.xcassets/LaunchImage.launchimage/Default-Landscape~ipad.png
--------------------------------------------------------------------------------
/platforms/ios/Ruby China/Images.xcassets/LaunchImage.launchimage/Default-Portrait@2x~ipad.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/platforms/ios/Ruby China/Images.xcassets/LaunchImage.launchimage/Default-Portrait@2x~ipad.png
--------------------------------------------------------------------------------
/platforms/ios/Ruby China/Images.xcassets/LaunchImage.launchimage/Default-Portrait~ipad.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/platforms/ios/Ruby China/Images.xcassets/LaunchImage.launchimage/Default-Portrait~ipad.png
--------------------------------------------------------------------------------
/platforms/ios/Ruby China/Images.xcassets/LaunchImage.launchimage/Default@2x~iphone.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/platforms/ios/Ruby China/Images.xcassets/LaunchImage.launchimage/Default@2x~iphone.png
--------------------------------------------------------------------------------
/platforms/ios/Ruby China/Images.xcassets/LaunchImage.launchimage/Default~iphone.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/platforms/ios/Ruby China/Images.xcassets/LaunchImage.launchimage/Default~iphone.png
--------------------------------------------------------------------------------
/platforms/ios/Ruby China/Ruby China-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | English
7 | CFBundleDisplayName
8 | ${PRODUCT_NAME}
9 | CFBundleExecutable
10 | ${EXECUTABLE_NAME}
11 | CFBundleIcons
12 |
13 | CFBundleIcons~ipad
14 |
15 | CFBundleIdentifier
16 | org.ruby-china.app
17 | CFBundleInfoDictionaryVersion
18 | 6.0
19 | CFBundleName
20 | ${PRODUCT_NAME}
21 | CFBundlePackageType
22 | APPL
23 | CFBundleShortVersionString
24 | 1.2.8
25 | CFBundleSignature
26 | ????
27 | CFBundleVersion
28 | 10
29 | GCM_SENDER_ID
30 | aaaaaa
31 | IS_GCM_ENABLED
32 |
33 | ITSAppUsesNonExemptEncryption
34 |
35 | LSRequiresIPhoneOS
36 |
37 | NSAppTransportSecurity
38 |
39 | NSAllowsArbitraryLoads
40 |
41 |
42 | NSMainNibFile~ipad
43 |
44 | UIBackgroundModes
45 |
46 | remote-notification
47 |
48 | UIRequiresFullScreen
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/platforms/ios/Ruby China/Ruby China-Prefix.pch:
--------------------------------------------------------------------------------
1 | /*
2 | Licensed to the Apache Software Foundation (ASF) under one
3 | or more contributor license agreements. See the NOTICE file
4 | distributed with this work for additional information
5 | regarding copyright ownership. The ASF licenses this file
6 | to you under the Apache License, Version 2.0 (the
7 | "License"); you may not use this file except in compliance
8 | with the License. You may obtain a copy of the License at
9 |
10 | http://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing,
13 | software distributed under the License is distributed on an
14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | KIND, either express or implied. See the License for the
16 | specific language governing permissions and limitations
17 | under the License.
18 | */
19 | //
20 | // Prefix header for all source files of the 'Ruby China' target in the 'Ruby China' project
21 | //
22 |
23 | #ifdef __OBJC__
24 | #import
25 | #import
26 | #endif
27 |
--------------------------------------------------------------------------------
/platforms/ios/Ruby China/config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | Ruby China
35 |
36 | Official Ruby China Mobile App for iOS and Android.
37 |
38 |
39 | Ruby China Team
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/platforms/ios/Ruby China/main.m:
--------------------------------------------------------------------------------
1 | /*
2 | Licensed to the Apache Software Foundation (ASF) under one
3 | or more contributor license agreements. See the NOTICE file
4 | distributed with this work for additional information
5 | regarding copyright ownership. The ASF licenses this file
6 | to you under the Apache License, Version 2.0 (the
7 | "License"); you may not use this file except in compliance
8 | with the License. You may obtain a copy of the License at
9 |
10 | http://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing,
13 | software distributed under the License is distributed on an
14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | KIND, either express or implied. See the License for the
16 | specific language governing permissions and limitations
17 | under the License.
18 | */
19 | //
20 | // main.m
21 | // Ruby China
22 | //
23 | // Created by ___FULLUSERNAME___ on ___DATE___.
24 | // Copyright ___ORGANIZATIONNAME___ ___YEAR___. All rights reserved.
25 | //
26 |
27 | #import
28 |
29 | int main(int argc, char* argv[])
30 | {
31 | @autoreleasepool {
32 | int retVal = UIApplicationMain(argc, argv, nil, @"AppDelegate");
33 | return retVal;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/platforms/ios/frameworks.json:
--------------------------------------------------------------------------------
1 | {
2 | "SafariServices.framework": 1,
3 | "AddressBook.framework": 1,
4 | "libsqlite3.tbd": 1,
5 | "libz.tbd": 1
6 | }
--------------------------------------------------------------------------------
/platforms/ios/ios.json:
--------------------------------------------------------------------------------
1 | {
2 | "prepare_queue": {
3 | "installed": [],
4 | "uninstalled": []
5 | },
6 | "config_munge": {
7 | "files": {
8 | "config.xml": {
9 | "parents": {
10 | "/*": [
11 | {
12 | "xml": "",
13 | "count": 1
14 | },
15 | {
16 | "xml": "",
17 | "count": 1
18 | },
19 | {
20 | "xml": "",
21 | "count": 1
22 | },
23 | {
24 | "xml": "",
25 | "count": 1
26 | },
27 | {
28 | "xml": "",
29 | "count": 1
30 | },
31 | {
32 | "xml": "",
33 | "count": 1
34 | },
35 | {
36 | "xml": "",
37 | "count": 1
38 | }
39 | ]
40 | }
41 | },
42 | "*-Info.plist": {
43 | "parents": {
44 | "UIBackgroundModes": [
45 | {
46 | "xml": "remote-notification",
47 | "count": 1
48 | }
49 | ],
50 | "GCM_SENDER_ID": [
51 | {
52 | "xml": "aaaaaa",
53 | "count": 1
54 | }
55 | ],
56 | "IS_GCM_ENABLED": [
57 | {
58 | "xml": "",
59 | "count": 1
60 | }
61 | ]
62 | }
63 | }
64 | }
65 | },
66 | "installed_plugins": {
67 | "cordova-plugin-app-version": {
68 | "PACKAGE_NAME": "org.ruby-china.app"
69 | },
70 | "cordova-plugin-device": {
71 | "PACKAGE_NAME": "org.ruby-china.app"
72 | },
73 | "cordova-plugin-safariviewcontroller": {
74 | "PACKAGE_NAME": "org.ruby-china.app"
75 | },
76 | "cordova-plugin-statusbar": {
77 | "PACKAGE_NAME": "org.ruby-china.app"
78 | },
79 | "cordova-plugin-whitelist": {
80 | "PACKAGE_NAME": "org.ruby-china.app"
81 | },
82 | "phonegap-plugin-push": {
83 | "SENDER_ID": "aaaaaa",
84 | "PACKAGE_NAME": "org.ruby-china.app"
85 | }
86 | },
87 | "dependent_plugins": {},
88 | "modules": [
89 | {
90 | "file": "plugins/cordova-plugin-app-version/www/AppVersionPlugin.js",
91 | "id": "cordova-plugin-app-version.AppVersionPlugin",
92 | "pluginId": "cordova-plugin-app-version",
93 | "clobbers": [
94 | "cordova.getAppVersion"
95 | ]
96 | },
97 | {
98 | "file": "plugins/cordova-plugin-device/www/device.js",
99 | "id": "cordova-plugin-device.device",
100 | "pluginId": "cordova-plugin-device",
101 | "clobbers": [
102 | "device"
103 | ]
104 | },
105 | {
106 | "file": "plugins/cordova-plugin-safariviewcontroller/www/SafariViewController.js",
107 | "id": "cordova-plugin-safariviewcontroller.SafariViewController",
108 | "pluginId": "cordova-plugin-safariviewcontroller",
109 | "clobbers": [
110 | "SafariViewController"
111 | ]
112 | },
113 | {
114 | "file": "plugins/cordova-plugin-statusbar/www/statusbar.js",
115 | "id": "cordova-plugin-statusbar.statusbar",
116 | "pluginId": "cordova-plugin-statusbar",
117 | "clobbers": [
118 | "window.StatusBar"
119 | ]
120 | },
121 | {
122 | "file": "plugins/phonegap-plugin-push/www/push.js",
123 | "id": "phonegap-plugin-push.PushNotification",
124 | "pluginId": "phonegap-plugin-push",
125 | "clobbers": [
126 | "PushNotification"
127 | ]
128 | }
129 | ],
130 | "plugin_metadata": {
131 | "cordova-plugin-app-version": "0.1.8",
132 | "cordova-plugin-device": "1.1.2",
133 | "cordova-plugin-safariviewcontroller": "1.4.3",
134 | "cordova-plugin-statusbar": "2.1.3",
135 | "cordova-plugin-whitelist": "1.2.2",
136 | "phonegap-plugin-push": "1.7.4"
137 | }
138 | }
--------------------------------------------------------------------------------
/platforms/platforms.json:
--------------------------------------------------------------------------------
1 | {
2 | "ios": "4.1.1"
3 | }
--------------------------------------------------------------------------------
/resources/android/icon/drawable-hdpi-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/resources/android/icon/drawable-hdpi-icon.png
--------------------------------------------------------------------------------
/resources/android/icon/drawable-ldpi-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/resources/android/icon/drawable-ldpi-icon.png
--------------------------------------------------------------------------------
/resources/android/icon/drawable-mdpi-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/resources/android/icon/drawable-mdpi-icon.png
--------------------------------------------------------------------------------
/resources/android/icon/drawable-xhdpi-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/resources/android/icon/drawable-xhdpi-icon.png
--------------------------------------------------------------------------------
/resources/android/icon/drawable-xxhdpi-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/resources/android/icon/drawable-xxhdpi-icon.png
--------------------------------------------------------------------------------
/resources/android/icon/drawable-xxxhdpi-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/resources/android/icon/drawable-xxxhdpi-icon.png
--------------------------------------------------------------------------------
/resources/android/splash/drawable-land-hdpi-screen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/resources/android/splash/drawable-land-hdpi-screen.png
--------------------------------------------------------------------------------
/resources/android/splash/drawable-land-ldpi-screen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/resources/android/splash/drawable-land-ldpi-screen.png
--------------------------------------------------------------------------------
/resources/android/splash/drawable-land-mdpi-screen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/resources/android/splash/drawable-land-mdpi-screen.png
--------------------------------------------------------------------------------
/resources/android/splash/drawable-land-xhdpi-screen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/resources/android/splash/drawable-land-xhdpi-screen.png
--------------------------------------------------------------------------------
/resources/android/splash/drawable-land-xxhdpi-screen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/resources/android/splash/drawable-land-xxhdpi-screen.png
--------------------------------------------------------------------------------
/resources/android/splash/drawable-land-xxxhdpi-screen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/resources/android/splash/drawable-land-xxxhdpi-screen.png
--------------------------------------------------------------------------------
/resources/android/splash/drawable-port-hdpi-screen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/resources/android/splash/drawable-port-hdpi-screen.png
--------------------------------------------------------------------------------
/resources/android/splash/drawable-port-ldpi-screen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/resources/android/splash/drawable-port-ldpi-screen.png
--------------------------------------------------------------------------------
/resources/android/splash/drawable-port-mdpi-screen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/resources/android/splash/drawable-port-mdpi-screen.png
--------------------------------------------------------------------------------
/resources/android/splash/drawable-port-xhdpi-screen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/resources/android/splash/drawable-port-xhdpi-screen.png
--------------------------------------------------------------------------------
/resources/android/splash/drawable-port-xxhdpi-screen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/resources/android/splash/drawable-port-xxhdpi-screen.png
--------------------------------------------------------------------------------
/resources/android/splash/drawable-port-xxxhdpi-screen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/resources/android/splash/drawable-port-xxxhdpi-screen.png
--------------------------------------------------------------------------------
/resources/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/resources/icon.png
--------------------------------------------------------------------------------
/resources/icon_trans.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/resources/icon_trans.png
--------------------------------------------------------------------------------
/resources/ios/icon/icon-40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/resources/ios/icon/icon-40.png
--------------------------------------------------------------------------------
/resources/ios/icon/icon-40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/resources/ios/icon/icon-40@2x.png
--------------------------------------------------------------------------------
/resources/ios/icon/icon-50.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/resources/ios/icon/icon-50.png
--------------------------------------------------------------------------------
/resources/ios/icon/icon-50@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/resources/ios/icon/icon-50@2x.png
--------------------------------------------------------------------------------
/resources/ios/icon/icon-60.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/resources/ios/icon/icon-60.png
--------------------------------------------------------------------------------
/resources/ios/icon/icon-60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/resources/ios/icon/icon-60@2x.png
--------------------------------------------------------------------------------
/resources/ios/icon/icon-60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/resources/ios/icon/icon-60@3x.png
--------------------------------------------------------------------------------
/resources/ios/icon/icon-72.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/resources/ios/icon/icon-72.png
--------------------------------------------------------------------------------
/resources/ios/icon/icon-72@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/resources/ios/icon/icon-72@2x.png
--------------------------------------------------------------------------------
/resources/ios/icon/icon-76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/resources/ios/icon/icon-76.png
--------------------------------------------------------------------------------
/resources/ios/icon/icon-76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/resources/ios/icon/icon-76@2x.png
--------------------------------------------------------------------------------
/resources/ios/icon/icon-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/resources/ios/icon/icon-small.png
--------------------------------------------------------------------------------
/resources/ios/icon/icon-small@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/resources/ios/icon/icon-small@2x.png
--------------------------------------------------------------------------------
/resources/ios/icon/icon-small@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/resources/ios/icon/icon-small@3x.png
--------------------------------------------------------------------------------
/resources/ios/icon/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/resources/ios/icon/icon.png
--------------------------------------------------------------------------------
/resources/ios/icon/icon@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/resources/ios/icon/icon@2x.png
--------------------------------------------------------------------------------
/resources/ios/splash/Default-568h@2x~iphone.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/resources/ios/splash/Default-568h@2x~iphone.png
--------------------------------------------------------------------------------
/resources/ios/splash/Default-667h.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/resources/ios/splash/Default-667h.png
--------------------------------------------------------------------------------
/resources/ios/splash/Default-736h.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/resources/ios/splash/Default-736h.png
--------------------------------------------------------------------------------
/resources/ios/splash/Default-Landscape-736h.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/resources/ios/splash/Default-Landscape-736h.png
--------------------------------------------------------------------------------
/resources/ios/splash/Default-Landscape@2x~ipad.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/resources/ios/splash/Default-Landscape@2x~ipad.png
--------------------------------------------------------------------------------
/resources/ios/splash/Default-Landscape~ipad.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/resources/ios/splash/Default-Landscape~ipad.png
--------------------------------------------------------------------------------
/resources/ios/splash/Default-Portrait@2x~ipad.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/resources/ios/splash/Default-Portrait@2x~ipad.png
--------------------------------------------------------------------------------
/resources/ios/splash/Default-Portrait~ipad.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/resources/ios/splash/Default-Portrait~ipad.png
--------------------------------------------------------------------------------
/resources/ios/splash/Default@2x~iphone.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/resources/ios/splash/Default@2x~iphone.png
--------------------------------------------------------------------------------
/resources/ios/splash/Default~iphone.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/resources/ios/splash/Default~iphone.png
--------------------------------------------------------------------------------
/resources/splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/resources/splash.png
--------------------------------------------------------------------------------
/scss/_base.scss:
--------------------------------------------------------------------------------
1 | html {
2 | // 16px = 1em; rem = root em 即根据 html 设置的百分比来
3 | // 因此设置字体基准:16px * 62.5% = 10px
4 | // 这样其他字体就可以这样定义:12px = 1.2rem,14px = 1.4rem
5 | font-size: 62.5%;
6 | }
7 |
8 | body {
9 | font-family: "Roboto", "RobotoDraft", "Helvetica Neue", Helvetica, Arial, sans-serif !important;
10 | }
11 |
12 | .bar-assertive {
13 | background-color: $assertive;
14 | box-shadow: 0 0px 1px rgba(0, 0, 0, 0.14);
15 | }
16 |
17 | .bar-header {
18 | .back-button {
19 | min-width: 35px;
20 | }
21 | }
22 |
23 | .bg-assertive,
24 | .bg-positive,
25 | .bg-balanced {
26 | color: $light;
27 | }
28 |
29 | .bg-assertive {
30 | background-color: $assertive;
31 | }
32 |
33 | .bg-positive {
34 | background-color: $positive;
35 | }
36 |
37 | .bg-stable {
38 | background-color: $stable;
39 | }
40 |
41 | .bg-balanced {
42 | background-color: $balanced;
43 | }
44 |
45 | .bg-light-gray {
46 | background-color: $light-gray;
47 | }
48 |
49 | /* 浮动按钮 */
50 | .button-fab {
51 | line-height: 0; padding: 0;
52 | border-radius: 180px;
53 | min-width: 45px; min-height: 45px;
54 | width: 45px; height: 45px;
55 | overflow: hidden;
56 | color: #FFF;
57 |
58 | box-shadow: 0 2px 2px rgba(0, 0, 0, 0.24);
59 |
60 | i { font-size: 28px; }
61 | }
62 |
63 | .button-fab-bottom-right {
64 | position: fixed;
65 | left: auto; top: auto;
66 | right: 20px; bottom: 20px;
67 | }
68 |
69 | .gray {
70 | color: $gray;
71 | }
72 |
73 | .black {
74 | color: black;
75 | }
76 |
77 | .item-narrow {
78 | min-height: 30px !important;
79 | padding: 6px 12px;
80 | .badge {
81 | display: flex;
82 | position: absolute;
83 | top: 6px;
84 | right: 0px;
85 | }
86 | }
87 |
88 | .item-block {
89 | min-height: 40px !important;
90 | padding: 0;
91 | }
92 |
93 | .item-bottom {
94 | position: absolute;
95 | bottom: 0;
96 | }
97 |
98 | .item-noborder {
99 | border: none !important;
100 | }
101 |
102 | .item-divider-narrow {
103 | min-height: 15px !important;
104 | }
105 |
106 | textarea {
107 | width: 98%;
108 | resize: none;
109 | box-sizing: border-box;
110 | overflow-x: hidden;
111 | overflow-y: scroll;
112 | }
113 |
114 | .text-sm {
115 | font-size: 14px;
116 | }
117 |
118 | .text-deleted {
119 | color: #aaa;
120 | font-size: 12px;
121 | margin-top: 6px;
122 | text-decoration: line-through;
123 | }
124 |
125 | .item h2 {
126 | font-weight: 300;
127 | }
128 |
129 | .pull-right {
130 | float: right;
131 | }
132 |
133 | .flat,
134 | .flat.button,
135 | .flat.button.icon,
136 | .flat.hero,
137 | .flat.tabs {
138 | border: 0px;
139 | box-shadow: 0 0 0 0;
140 | }
141 |
142 | .list .item-avatar {
143 | min-height: 80px;
144 | }
145 |
146 | .list .item {
147 | border: 0.06em solid #e0e0e0;
148 | }
149 |
150 | .item.active,
151 | .item.activated,
152 | .item-complex.active .item-content,
153 | .item-complex.activated .item-content,
154 | .item .item-content.active,
155 | .item .item-content.activated {
156 | background: #FFFAF4;
157 | }
158 |
159 | .card>.item-avatar,
160 | .item-avatar,
161 | .item-avatar .item-content,
162 | .item-avatar-left,
163 | .item-avatar-left .item-content {
164 | padding-left: 70px;
165 | }
166 |
167 | .item,
168 | .item h1,
169 | .item h2,
170 | .item h3,
171 | .item h4,
172 | .item h5,
173 | .item h6,
174 | .item p,
175 | .item-content,
176 | .item-content h1,
177 | .item-content h2,
178 | .item-content h3,
179 | .item-content h4,
180 | .item-content h5,
181 | .item-content h6,
182 | .item-content p {
183 | font-family: Helvetica,Arial,"PingFang SC","Hiragino Sans GB","Source Han Sans CN",Roboto,"Heiti SC","Microsoft Yahei",sans-serif !important;
184 | white-space: normal;
185 | }
186 |
187 | .action-sheet {
188 | .button {
189 | box-shadow: none;
190 | }
191 | }
192 |
193 | // .keyboard-open {
194 | // .bar-footer {
195 | // transform: translate3d(0px, -213px, 0px) !important;
196 | // }
197 | // }
198 |
199 | #loading-bar .bar {
200 | top:0px !important;
201 | }
202 |
203 | #loading-bar-spinner {
204 | display: none;
205 | }
206 |
--------------------------------------------------------------------------------
/scss/_markdown.scss:
--------------------------------------------------------------------------------
1 | /* Markdown Styles */
2 |
3 | /* Markdown Styles */
4 | .markdown {
5 | position:relative;
6 | line-height: 1.8em; font-size:14px; text-overflow: ellipsis; word-wrap: break-word;
7 | font-family: "PingFang SC","Hiragino Sans GB",Helvetica,Arial,"Source Han Sans CN",Roboto,"Heiti SC","Microsoft Yahei",sans-serif !important;
8 | img { max-width: 100%; }
9 | p,
10 | pre,
11 | ul,
12 | ol,
13 | blockquote { margin-bottom: 16px; }
14 |
15 | p { font-size: 14px; line-height: 1.5em; }
16 | hr { border:2px dashed $gray; border-bottom:0px; margin: 18px auto; width:50%; }
17 | blockquote {
18 | margin: 0 18px 15px 18px;
19 | padding: 0;
20 | padding-left: 32px;
21 | border: 0px;
22 | quotes: "\201C""\201D""\2018""\2019";
23 | position: relative;
24 | line-height: 1.45;
25 | p { display:inline; color: #999; }
26 | &:before,
27 | &:after {
28 | display: block;
29 | content: "\201C";
30 | font-size: 35px;
31 | position: absolute;
32 | font-family: serif;
33 | left: 0px;
34 | top: 0px;
35 | color: #aaa;
36 | }
37 | }
38 | pre {
39 | font-family: Menlo, Monaco, "Courier New", monospace;
40 | font-size: 12px;
41 | background-color: #F5F5F5;
42 | border: 0px;
43 | padding: 5px;
44 | color: #444;
45 | overflow: auto;
46 | border-radius: 0px;
47 | code {
48 | display: block;
49 | line-height: 150%;
50 | padding: 0!important;
51 | font-size: 12px!important;
52 | background-color: #F5F5F5 !important;
53 | border: none!important; }
54 | }
55 | p:last-child,
56 | blockquote:last-child,
57 | pre:last-child { margin-bottom:0; }
58 | pre::-webkit-scrollbar {
59 | height: 8px;
60 | width: 8px; }
61 |
62 | pre::-webkit-scrollbar-thumb:horizontal {
63 | width: 25px;
64 | background-color: #ccc;
65 | -webkit-border-radius: 4px; }
66 |
67 | pre::-webkit-scrollbar-track-piece {
68 | margin-bottom: 10px;
69 | background-color: #e5e5e5;
70 | border-bottom-left-radius: 4px 4px;
71 | border-bottom-right-radius: 4px 4px;
72 | border-top-left-radius: 4px 4px;
73 | border-top-right-radius: 4px 4px; }
74 |
75 | pre::-webkit-scrollbar-thumb:vertical {
76 | height: 25px;
77 | background-color: #ccc;
78 | -webkit-border-radius: 4px;
79 | -webkit-box-shadow: 0 1px 1px white; }
80 |
81 | code {
82 | font-size: 12px!important;
83 | background-color: #F5F5F5 !important;
84 | color: #444 !important;
85 | padding: 1px 2px !important;
86 | border: 0px;
87 | margin: 2px;
88 | border-radius: 0px;
89 | word-break: break-all;
90 | line-height: 20px;
91 | font-family:Monaco,Menlo, "Courier New", monospace;
92 | }
93 | a:link,
94 | a:visited {
95 | color:#0069D6 !important; text-decoration: none !important;
96 | }
97 | a:hover { text-decoration: underline !important; color:#00438A !important; }
98 | a.mention-floor { color:#60b566 !important; margin-right: 3px; }
99 | a.mention {
100 | color:#777 !important; font-weight: bold;
101 | margin-right: 2px;
102 | b { color:#777 !important; font-weight: normal; }
103 | }
104 | h1,
105 | h2,
106 | h3,
107 | h4,
108 | h5,
109 | h6 {
110 | font-weight:bold; text-align:left;
111 | margin-top: 10px !important; margin-bottom: 16px;
112 | }
113 | h1 { font-size: 26px !important; text-align: center; margin-bottom: 30px !important; }
114 | h2,
115 | h3,
116 | h4 {
117 | text-align: left;
118 | font-weight: bold;
119 | font-size: 16px !important;
120 | line-height: 100%;
121 | margin: 0; color: #555;
122 | margin-top: 16px; margin-bottom:16px;
123 | border-bottom:1px solid #eee;
124 | padding-bottom: 5px;
125 | }
126 | h2 { font-size: 20px !important; border-bottom-width: 2px; padding-bottom: 15px; margin-top: 20px; margin-bottom:20px; color: #111; }
127 | h3 { font-size: 18px !important; padding-bottom: 10px; margin-top: 20px; margin-bottom: 20px; color: #333; }
128 | h5, h6 { font-size: 15px; line-height: 100%; color: #777; }
129 | h6 { font-size: 14px; color: #999; }
130 |
131 | strong { color:#000; }
132 | ul,
133 | ol {
134 | list-style-position: inside;
135 | list-style-type: square;
136 | margin:0;
137 | margin-bottom: 20px;
138 | padding:0px 20px;
139 | p,
140 | blockquote,
141 | pre { margin-bottom:8px; }
142 | li { line-height:1.6em; padding:2px 0; color:#333; }
143 | ul { list-style-type: circle; margin-bottom: 0px; }
144 | }
145 | ol {
146 | list-style-type: decimal;
147 | ol { list-style-type: lower-alpha; margin-bottom: 0px; }
148 | }
149 | img { vertical-align: top; max-width: 100%; }
150 | a.zoom-image { cursor: zoom-in; }
151 | a.at_floor { color: #60B566 !important; }
152 | a.at_user { color: #0069D6 !important; }
153 | img.twemoji { width: 20px; }
154 | }
155 |
156 | .highlight .hll { background-color: #ffffcc }
157 | .highlight .c { color: #B0B2B0; font-style: italic } /* Comment */
158 | .highlight .err { } /* Error */
159 | .highlight .k { color: #AA22FF; font-weight: bold } /* Keyword */
160 | .highlight .o { color: #666666 } /* Operator */
161 | .highlight .cm { color: #B0B2B0; font-style: italic } /* Comment.Multiline */
162 | .highlight .cp { color: #B0B2B0 } /* Comment.Preproc */
163 | .highlight .c1 { color: #B0B2B0; font-style: italic } /* Comment.Single */
164 | .highlight .cs { color: #B0B2B0; font-weight: bold } /* Comment.Special */
165 | .highlight .gd { color: #A00000 } /* Generic.Deleted */
166 | .highlight .ge { font-style: italic } /* Generic.Emph */
167 | .highlight .gr { color: #FF0000 } /* Generic.Error */
168 | .highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
169 | .highlight .gi { color: #00A000 } /* Generic.Inserted */
170 | .highlight .go { color: #808080 } /* Generic.Output */
171 | .highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
172 | .highlight .gs { font-weight: bold } /* Generic.Strong */
173 | .highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
174 | .highlight .gt { color: #0040D0 } /* Generic.Traceback */
175 | .highlight .kc { color: #AA22FF; font-weight: bold } /* Keyword.Constant */
176 | .highlight .kd { color: #AA22FF; font-weight: bold } /* Keyword.Declaration */
177 | .highlight .kn { color: #AA22FF; font-weight: bold } /* Keyword.Namespace */
178 | .highlight .kp { color: #AA22FF } /* Keyword.Pseudo */
179 | .highlight .kr { color: #AA22FF; font-weight: bold } /* Keyword.Reserved */
180 | .highlight .kt { color: #00BB00; font-weight: bold } /* Keyword.Type */
181 | .highlight .m { color: #666666 } /* Literal.Number */
182 | .highlight .s { color: #BB4444 } /* Literal.String */
183 | .highlight .na { color: #BB4444 } /* Name.Attribute */
184 | .highlight .nb { color: #AA22FF } /* Name.Builtin */
185 | .highlight .nc { color: #0000FF } /* Name.Class */
186 | .highlight .no { color: #880000 } /* Name.Constant */
187 | .highlight .nd { color: #AA22FF } /* Name.Decorator */
188 | .highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */
189 | .highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
190 | .highlight .nf { color: #00A000 } /* Name.Function */
191 | .highlight .nl { color: #A0A000 } /* Name.Label */
192 | .highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
193 | .highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */
194 | .highlight .nv { color: #B8860B } /* Name.Variable */
195 | .highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
196 | .highlight .w { color: #bbbbbb } /* Text.Whitespace */
197 | .highlight .mf { color: #666666 } /* Literal.Number.Float */
198 | .highlight .mh { color: #666666 } /* Literal.Number.Hex */
199 | .highlight .mi { color: #666666 } /* Literal.Number.Integer */
200 | .highlight .mo { color: #666666 } /* Literal.Number.Oct */
201 | .highlight .sb { color: #BB4444 } /* Literal.String.Backtick */
202 | .highlight .sc { color: #BB4444 } /* Literal.String.Char */
203 | .highlight .sd { color: #BB4444; font-style: italic } /* Literal.String.Doc */
204 | .highlight .s2 { color: #BB4444 } /* Literal.String.Double */
205 | .highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
206 | .highlight .sh { color: #BB4444 } /* Literal.String.Heredoc */
207 | .highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
208 | .highlight .sx { color: #008000 } /* Literal.String.Other */
209 | .highlight .sr { color: #BB6688 } /* Literal.String.Regex */
210 | .highlight .s1 { color: #BB4444 } /* Literal.String.Single */
211 | .highlight .ss { color: #B8860B } /* Literal.String.Symbol */
212 | .highlight .bp { color: #AA22FF } /* Name.Builtin.Pseudo */
213 | .highlight .vc { color: #B8860B } /* Name.Variable.Class */
214 | .highlight .vg { color: #B8860B } /* Name.Variable.Global */
215 | .highlight .vi { color: #B8860B } /* Name.Variable.Instance */
216 | .highlight .il { color: #666666 } /* Literal.Number.Integer.Long */
217 |
--------------------------------------------------------------------------------
/scss/_menu.scss:
--------------------------------------------------------------------------------
1 | #main-menu {
2 | .list {
3 | &.bottom {
4 | position: absolute;
5 | bottom: 0;
6 | width: 100%;
7 | }
8 | .item {
9 | min-height: 41px;
10 | font-size: 14px;
11 | .icon {
12 | font-size: 24px;
13 | }
14 | }
15 |
16 | .item-version { font-size: 12px; color: #AAA; }
17 |
18 | .item-notification {
19 | .count { display: none; }
20 | &.active {
21 | .count {
22 | margin-top: 2px;
23 | line-height: 100%;
24 | float: right;
25 | display: inline;
26 | background: #F95721;
27 | font-size: 10px;
28 | padding: 2px 8px;
29 | color: #FFF;
30 | border-radius: 180px;
31 | }
32 | }
33 | }
34 | }
35 | }
36 |
37 | .bar .button.button-icon.new { color:#F9F33B; }
38 | .bar .button .back-text { display:none; }
39 |
40 | .user-bar {
41 | background: #FFF;
42 | border-bottom: 2px solid #D2D2D2;
43 | h2 {
44 | font-size: 15px;
45 | color: #222;
46 | font-weight: 400;
47 | }
48 | .level {
49 | font-size: 10px;
50 | color: #9B9B9B;
51 | }
52 | }
53 |
54 | #new-topic-modal {
55 | .node_seletor {
56 | color: #aaa;
57 | direction: ltr;
58 | max-width: 100%;
59 | padding-left: 0;
60 | padding-top: 6px;
61 | padding-bottom: 5px;
62 | }
63 | .has_node {
64 | left: 36px;
65 | }
66 | .tabs-topic {
67 | height: 40px;
68 | .icon {
69 | line-height: 36px;
70 | height: 26px;
71 | font-size: 26px;
72 | }
73 | }
74 | }
75 |
76 | .code_selector {
77 | height: 50%;
78 | top: 20%;
79 | }
80 |
--------------------------------------------------------------------------------
/scss/_notifications.scss:
--------------------------------------------------------------------------------
1 | #notifications {
2 | .list {
3 | .no-result {
4 | padding: 20px;
5 | text-align: center;
6 | font-size: 14px;
7 | color: #666;
8 | }
9 | .item {
10 | padding: 10px 16px 10px 58px;
11 | min-height: 55px;
12 | img { top: 8px; left: 10px; }
13 | h2 {
14 | padding-right: 20px;
15 | margin-top: 3px;
16 | font-size: 12px;
17 | font-weight: 350;
18 | color: #666;
19 | margin-bottom: 6px;
20 | }
21 | .notify-title { color: #888; font-weight: bold; margin-bottom: 10px; }
22 | .author {
23 | font-size: 13px;
24 | margin-top: 5px;
25 | font-weight: 400;
26 | color: #555;
27 | }
28 | .badge {
29 | background: #F94D24;
30 | display: block;
31 | position: absoulte;
32 | width: 10px; height: 10px;
33 | font-size: 12px;
34 | line-height: 100%;
35 | padding: 2px;
36 | font-weight: normal;
37 | right: 5px;
38 | }
39 |
40 | .positive { color: #333; font-size: 14px;}
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/scss/_topic.scss:
--------------------------------------------------------------------------------
1 | #topic-detail {
2 | .list {
3 | padding-bottom: 80px;
4 |
5 | .gray,
6 | .dark { color: #929292; font-size: 12px; }
7 | .toolbar {
8 | height: 0px;
9 | overflow: hidden;
10 | perspective: 200px;
11 | position: relative;
12 | transition: height 0.2s ease-in-out;
13 | border-top: 0px;
14 | .tab-item {
15 | i { font-size: 24px; }
16 | }
17 |
18 | .tabs {
19 | position: absolute;
20 | opacity: 0;
21 | background: #FFE054;
22 | transition: all 0.3s ease-in-out;
23 | transform: rotateX(60deg);
24 |
25 | .active { color: #DC5B2E; }
26 | }
27 |
28 | &.open .tabs {
29 | opacity: 1;
30 | transform: rotateX(0deg);
31 | }
32 |
33 | .fold-top, .fold-bottom {
34 | height: 20px;
35 | width: 312px;
36 | left: 4px;
37 | position: absolute;
38 | transition: all 0.32s ease-in-out;
39 | }
40 |
41 | &.open .fold-top, &.open .fold-bottom {
42 | background: #FFE054;
43 | transform: rotateX(0deg);
44 | width: 100%;
45 | left: 0;
46 | }
47 |
48 | .fold-top {
49 | transform-origin: top center;
50 | transform: rotateX(-90deg);
51 | top: 0;
52 | background: #FFE054;
53 | }
54 |
55 | .fold-bottom {
56 | transform-origin: bottom center;
57 | transform: rotateX(90deg);
58 | bottom: 0;
59 | background: #FFE054;
60 | }
61 | }
62 | .toolbar.open {
63 | height: 48px;
64 | }
65 | .item-avatar {
66 | min-height: 53px;
67 | border-bottom: none;
68 | padding: 6px 10px 6px 48px;
69 | img { width: 30px; height: 30px; top: 12px; left: 10px; }
70 | h2 {
71 | font-size: 13px; line-height: 30px;
72 | .gray { font-size: 0.8em; }
73 | }
74 | }
75 |
76 | .item {
77 | border-bottom: 1px solid $light-gray;
78 |
79 | .topic-title { font-weight: 500; font-size: 16px; }
80 |
81 | .active { color: #E34A2A;}
82 |
83 | span {
84 | font-size: 12px;
85 | }
86 |
87 | &.item-info {
88 | background: #f9f9f9; color: #555;
89 | span { font-size: 14px; }
90 | i { font-size: 15px; }
91 | }
92 |
93 | h2,
94 | h3 {
95 | font-weight: 300;
96 | }
97 | h2 {
98 | line-height: 40px;
99 | }
100 | h3 {
101 | font-size: 18px;
102 | }
103 |
104 | &.reply {
105 | .row { padding: 0px; }
106 | padding-top: 0;
107 | .item-avatar {
108 | padding: 10px 0;
109 | padding-left: 36px;
110 | img:first-child {
111 | position: absolute;
112 | max-width: 30px;
113 | max-height: 30px;
114 | top: 10px;
115 | }
116 | h2 {
117 | line-height: 30px !important;
118 | font-size: 13px; color: #202020;
119 | .like {
120 | margin-right: 8px;
121 | color: #AAA;
122 |
123 | i { color: #DDD; }
124 | &.active i { color: #E34A2A; }
125 | }
126 | .floor {
127 | font-size: 12px;
128 | color: #8AAA9B;
129 | margin-right: 6px;
130 | }
131 | .time { color: #AAA; font-size:11px;}
132 | }
133 | }
134 | }
135 | }
136 | }
137 |
138 | .replies-divider { padding: 2px; min-height: 5px; }
139 | }
140 |
141 | #reply-modal {
142 | .item-reply {
143 | min-height: 250px;
144 | #topic-reply {
145 | padding: 10px;
146 | }
147 | }
148 | }
149 |
--------------------------------------------------------------------------------
/scss/_topics.scss:
--------------------------------------------------------------------------------
1 | #topics {
2 | .list {
3 | .item {
4 | &:visited {
5 | h2 {
6 | color: #666;
7 | }
8 | }
9 |
10 | .item-content {
11 | min-height: 5.5rem;
12 | padding: 5px 32px 5px 64px;
13 | img {
14 | top: 8px; left: 12px;
15 | }
16 | h2 {
17 | margin-top: 5px;
18 | font-size: 1.4rem;
19 | font-weight: 400;
20 | }
21 | &:visited {
22 | h2 {
23 | color: #666;
24 | }
25 | }
26 | }
27 | .badge {
28 | color: #ababab;
29 | font-size: 1.2rem;
30 | font-weight: normal;
31 | right: 8px;
32 | }
33 | .author {
34 | font-size: 1.1rem;
35 | line-height: 1.1rem;
36 | margin-top: 5px;
37 | color: #959595;
38 | .node {
39 | margin-right: 6px;
40 | font-weight: bold;
41 | }
42 | }
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/scss/_user.scss:
--------------------------------------------------------------------------------
1 | #user-profile {
2 | .list {
3 | .item {
4 | margin-bottom: 1px;
5 | }
6 | .item-avatar,
7 | .item-follow .col,
8 | .item-narrow {
9 | background-color: white;
10 | }
11 | .item-divider {
12 | padding: 0;
13 | border-top: none;
14 | background-color: #F9F9F9;
15 | line-height: inherit;
16 | height: auto;
17 | .row {
18 | .button-round {
19 | max-height: 30px;
20 | max-width: 100px;
21 | padding: 0 10px;
22 | border-radius: 15px;
23 | width: 100px;
24 | .icon,
25 | .icon:before {
26 | font-size: 20px;
27 | }
28 | }
29 | }
30 | }
31 | .item-avatar {
32 | min-height: 100px;
33 | padding: 20px;
34 | text-align: center;
35 | img:first-child {
36 | max-width: 80px;
37 | max-height: 80px;
38 | position: initial;
39 | }
40 | .level {
41 | position: absolute;
42 | top: 10px;
43 | right: 10px;
44 | padding: 3px;
45 | border-radius: 2px;
46 | font-size: 12px;
47 | line-height: 14px;
48 | font-weight: 400;
49 | }
50 | h2,.positive { font-size: 14px; font-weight: normal; }
51 | .positive { font-size: 13px; font-weight: normal; color: #5E97F6; }
52 | }
53 | .user-time { font-size: 12px; color: #CCC; }
54 | .item-follow {
55 | padding: 0;
56 | border-width: 0px;
57 | .row {
58 | padding: 1px;
59 | font-size: 12px;
60 | color: #222;
61 | .positive { color: #5E97F6; font-size: 22px; }
62 | .col {
63 | padding: 20px 20px 10px;
64 | &:first-child {
65 | margin-right: 1px;
66 | }
67 | }
68 | .positive {
69 | font-size: 30px;
70 | margin-bottom: 10px;
71 | }
72 | }
73 | }
74 | .item-info {
75 | &:active {
76 | background: #FFFAF4;
77 | }
78 | i {
79 | font-size: 18px;
80 | margin-right: 4px;
81 | vertical-align: middle;
82 | }
83 | a,
84 | span.text {
85 | color: #222;
86 | text-decoration: none;
87 | font-size: 13px;
88 | }
89 | .badge { background-color: transparent; color: #999; text-align: right; font-size: 11px; font-weight: normal; }
90 | }
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/scss/style.scss:
--------------------------------------------------------------------------------
1 | /*
2 | To customize the look and feel of Ionic, you can override the variables
3 | in ionic's _variables.scss file.
4 |
5 | For example, you might change some of the default colors:
6 | */
7 |
8 | $light: #fff !default;
9 | $stable: #f8f8f8 !default;
10 | $positive: #387ef5 !default;
11 | $calm: #11c1f3 !default;
12 | $balanced: #33cd5f !default;
13 | $energized: #ffc900 !default;
14 | $assertive: #ef473a !default;
15 | $royal: #886aea !default;
16 | $dark: #444 !default;
17 | $light-gray: #f1f1f1 !default;
18 | $gray: #acacac !default;
19 | $RobotoDraftFontPath: "../lib/robotodraft/fonts" !default;
20 | $RobotoDraftFontName: "RobotoDraft";
21 | $RobotoDraftFontVersion: "1.0.0";
22 | @import "www/lib/robotodraft/sass/robotodraft";
23 | // Modules
24 | @import "base";
25 | @import "markdown";
26 | @import "menu";
27 | @import "topics";
28 | @import "topic";
29 | @import "user";
30 | @import "notifications";
31 |
--------------------------------------------------------------------------------
/www/img/default_avatar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/www/img/default_avatar.png
--------------------------------------------------------------------------------
/www/img/ionic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ruby-china/ruby-china-ionic/2fc20f363e5908d067a6202a054702d8fa9a1e5a/www/img/ionic.png
--------------------------------------------------------------------------------
/www/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/www/js/app.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | 'use strict';
3 |
4 | angular
5 | .module('rbchina', [
6 | 'app.core',
7 | 'app.filter',
8 | 'app.controller',
9 | 'app.service'
10 | ]);
11 | })();
12 |
--------------------------------------------------------------------------------
/www/js/controllers/controller.module.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | 'use strict';
3 |
4 | angular
5 | .module('app.controller', []);
6 |
7 | })();
8 |
--------------------------------------------------------------------------------
/www/js/controllers/notifications.controller.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | 'use strict';
3 |
4 | angular
5 | .module('app.controller')
6 | .controller('NotificationsController', NotificationsController);
7 |
8 | ////////////////////////////////////////////////////////////
9 |
10 | /* @ngInject */
11 | function NotificationsController($scope, $rootScope, BaseService, UserService) {
12 | var vm = this;
13 | vm.current_page = 1; // 当前页码
14 | vm.notifications = [];
15 |
16 | // Functions
17 | vm.doRefresh = doRefresh;
18 | vm.loadMore = loadMore;
19 | vm.deleteAllNotifications = deleteAllNotifications;
20 |
21 | activate();
22 |
23 | function activate() {
24 | vm.current_page = 1;
25 |
26 | loadData().then(function(result) {
27 | vm.notifications = result;
28 | var unread_items = _.filter(result, function(item) {
29 | return item.read == false;
30 | });
31 | var ids = _.pluck(unread_items, 'id');
32 | UserService.markNotificationsRead(ids);
33 |
34 | $rootScope.$broadcast('unread_notifications_count', 0);
35 |
36 | // BaseService.formatTopicBody();
37 | });
38 | }
39 |
40 | function loadData(offset) {
41 | return UserService.getUserNotifications(offset)
42 | .then(function(result) {
43 | return result;
44 | });
45 | }
46 |
47 | function doRefresh() {
48 | vm.current_page = 1;
49 | loadData().then(function(result) {
50 | vm.notifications = result;
51 | $scope.$broadcast('scroll.refreshComplete');
52 | });
53 | }
54 |
55 | function loadMore() {
56 | vm.current_page++;
57 | return loadData(vm.current_page)
58 | .then(function(result) {
59 | vm.has_more = result.items && result.items.length > 0;
60 | if (!vm.has_more) {
61 | vm.current_page--;
62 | } else {
63 | vm.notifications = _.union(vm.notifications, result.items);
64 | $scope.$broadcast('scroll.infiniteScrollComplete');
65 | }
66 | });
67 | }
68 |
69 | function deleteAllNotifications() {
70 | BaseService.confirm("清除通知", "", "确定要将你的所有通知清空吗?").then(function(res) {
71 | if (res) {
72 | UserService.deleteAllNotifications().then(function(res) {
73 | doRefresh();
74 | });
75 | }
76 | });
77 | }
78 |
79 | $scope.$on('$ionicView.beforeEnter', function(viewInfo, state) {
80 | BaseService.statusBar(0);
81 | });
82 |
83 | }
84 |
85 | })();
86 |
--------------------------------------------------------------------------------
/www/js/controllers/topic.controller.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | 'use strict';
3 |
4 | angular
5 | .module('app.controller')
6 | .controller('TopicController', TopicController);
7 |
8 | ////////////////////////////////////////////////////////////
9 |
10 | /* @ngInject */
11 | function TopicController($rootScope, $scope, $stateParams, $timeout, $ionicActionSheet,
12 | $ionicPopup, $location, $ionicPosition, $ionicScrollDelegate,
13 | BaseService, AuthService, TopicService, CameraService) {
14 |
15 | var vm = this;
16 | vm.is_logined = false;
17 | vm.current_user = null;
18 | vm.user_liked_reply_ids = [];
19 | vm.meta = {};
20 | vm.topic = {
21 | user: {
22 | avatar_url: 'img/default_avatar.png'
23 | },
24 | likes_count: 0,
25 | body_html: '',
26 | title: ''
27 | };
28 | vm.replies = [];
29 | vm.reply_content = "";
30 | vm.current_page = 1; // 当前页码
31 |
32 | // Functions
33 | vm.showReplies = showReplies;
34 | vm.showTopicPopupMenu = showTopicPopupMenu;
35 | vm.showReplyModal = showReplyModal;
36 | vm.closeReplyModal = closeReplyModal;
37 | vm.moreAction = moreAction;
38 | vm.saveReply = saveReply;
39 | vm.loadMore = loadMore;
40 | vm.quoteReply = quoteReply;
41 | vm.editReply = editReply;
42 | vm.destroyReply = destroyReply;
43 | vm.likeReply = likeReply;
44 | vm.isReplyLiked = isReplyLiked;
45 |
46 | activate();
47 |
48 | function openUrl() {
49 | console.log('open');
50 | }
51 |
52 | function activate() {
53 |
54 | vm.is_logined = AuthService.isAuthencated();
55 | vm.current_user = AuthService.getCurrentUser();
56 | vm.reply_content = "";
57 | BaseService.registModal('modals/reply.html', 'reply-modal', $scope, {
58 | focusFirstInput: true
59 | });
60 |
61 | TopicService.getTopic($stateParams.topic_id).then(function(result) {
62 | vm.meta = result.meta;
63 | vm.topic = result.topic;
64 | // BaseService.formatTopicBody();
65 | });
66 |
67 | TopicService.getRepliesByTopic($stateParams.topic_id, 0).then(function(result) {
68 | vm.replies = result.replies;
69 | vm.user_liked_reply_ids = result.meta.user_liked_reply_ids || [];
70 | vm.has_more = vm.replies.length === 150; // 默认这里 100 条一页
71 | // BaseService.formatTopicBody();
72 | });
73 | }
74 |
75 | function showReplyModal() {
76 | vm.edit_reply_id = null;
77 | vm.reply_content = "";
78 | vm.is_logined = AuthService.isAuthencated();
79 | if (!vm.is_logined) {
80 | BaseService.showModal('login-modal');
81 | } else {
82 | BaseService.showModal('reply-modal');
83 | }
84 | }
85 |
86 | function quoteReply(reply, floor) {
87 | vm.current_edit_reply = null;
88 | vm.reply_content = "#" + floor + "楼 @" + reply.user.login + " ";
89 | BaseService.showModal('reply-modal');
90 | }
91 |
92 | function likeReply(reply) {
93 | var liked = isReplyLiked(reply);
94 | TopicService.like('reply', reply.id, liked).then(function(result) {
95 | reply.likes_count = result.count;
96 | if (liked) {
97 | _.remove(vm.user_liked_reply_ids, function(id) {
98 | return id == reply.id
99 | });
100 | } else {
101 | vm.user_liked_reply_ids.push(reply.id);
102 | }
103 | });
104 | }
105 |
106 | function isReplyLiked(reply) {
107 | return vm.user_liked_reply_ids.indexOf(reply.id) != -1;
108 | }
109 |
110 | function editReply(reply) {
111 | vm.current_edit_reply = reply;
112 | TopicService.getReply(reply.id).then(function(result) {
113 | vm.reply_content = result.reply.body;
114 | BaseService.showModal('reply-modal');
115 | });
116 | }
117 |
118 | function destroyReply(reply) {
119 | BaseService.confirm('删除确认', '', '你确定要删除这个回帖么?').then(function(res) {
120 | TopicService.destroyReply(reply.id).then(function(result) {
121 | reply.deleted = true;
122 | });
123 | });
124 | }
125 |
126 | function closeReplyModal() {
127 | BaseService.hideModal('reply-modal');
128 | }
129 |
130 | function showTopicPopupMenu() {
131 | vm.is_logined = AuthService.isAuthencated();
132 | if (!vm.is_logined) {
133 | BaseService.showModal('login-modal');
134 | return true;
135 | };
136 |
137 | var likeButton = { text: ' 赞' };
138 | var unlikeButton = { text: ' 取消赞' };
139 | var favoriteButton = { text: ' 收藏' };
140 | var unfavoriteButton = { text: ' 取消收藏' };
141 | var followButton = { text: ' 关注' };
142 | var unfollowButton = { text: ' 取消关注' };
143 | var banButton = { text: ' 屏蔽' };
144 | var deleteButton = { text: ' 删除' };
145 |
146 | var buttons = [];
147 | if (vm.meta.liked) {
148 | buttons.push(unlikeButton);
149 | } else {
150 | buttons.push(likeButton);
151 | }
152 |
153 | if (vm.meta.favorited) {
154 | buttons.push(unfavoriteButton);
155 | } else {
156 | buttons.push(favoriteButton);
157 | }
158 |
159 | if (vm.meta.followed) {
160 | buttons.push(unfollowButton);
161 | } else {
162 | buttons.push(followButton);
163 | }
164 |
165 | if (vm.is_logined && vm.current_user.level == 'admin') {
166 | buttons.push(banButton);
167 | }
168 |
169 | if (vm.topic.abilities.destroy) {
170 | buttons.push(deleteButton);
171 | }
172 |
173 | var options = {
174 | buttons: buttons,
175 | cancelText: '取消',
176 | buttonClicked: function(index) {
177 | if (index == buttons.indexOf(likeButton)) {
178 | TopicService.likeTopic(vm.topic.id).then(function(result) {
179 | vm.topic.likes_count = result.count;
180 | vm.meta.liked = true;
181 | });
182 | }
183 |
184 | if (index == buttons.indexOf(unlikeButton)) {
185 | TopicService.unlikeTopic(vm.topic.id).then(function(result) {
186 | vm.topic.likes_count = result.count;
187 | vm.meta.liked = false;
188 | });
189 | }
190 |
191 | if (index == buttons.indexOf(favoriteButton) || index == buttons.indexOf(unfavoriteButton)) {
192 | TopicService.favorite(vm.topic.id, vm.meta.favorited).then(function(res) {
193 | vm.meta.favorited = !vm.meta.favorited;
194 | });
195 | }
196 |
197 | if (index == buttons.indexOf(followButton) || index == buttons.indexOf(unfollowButton)) {
198 | TopicService.follow(vm.topic.id, vm.meta.followed).then(function(res) {
199 | vm.meta.followed = !vm.meta.followed;
200 | });
201 | }
202 |
203 | if (index == buttons.indexOf(banButton)) {
204 | TopicService.ban(vm.topic.id).then(function(res) {
205 | BaseService.alert('屏蔽话题', '', '已经成功将话题移到了 NoPoint 节点。');
206 | vm.topic.node_name = "NoPoint";
207 | });
208 | }
209 |
210 | if (index == buttons.indexOf(deleteButton)) {
211 | BaseService.confirm('删除确认', '', '你确定要删除这个话题么?').then(function(res) {
212 | TopicService.destroy(vm.topic.id).then(function(result) {
213 | $location.path('/app/topics/last_actived');
214 | });
215 | });
216 | }
217 |
218 | return true;
219 | }
220 | };
221 | return $ionicActionSheet.show(options);
222 | }
223 |
224 | function moreAction() {
225 | var options = {
226 | buttons: [{
227 | text: ' 从相册添加图片'
228 | }, {
229 | text: ' 从相机添加图片'
230 | }],
231 | titleText: '更多',
232 | cancelText: '取消',
233 | buttonClicked: function(index) {
234 | document.addEventListener("deviceready", function() {
235 | var size = {
236 | width: 800,
237 | height: 600
238 | };
239 | return CameraService.getPicture(index, size, 0)
240 | .then(function(result) {
241 | BaseService.uploadPicture(result)
242 | .then(function(img) {
243 | var img_url = '';
244 | var prev = vm.reply_content.length === 0 ? '' : vm.reply_content + "\r\n";
245 | vm.reply_content = prev + img_url;
246 | });
247 | });
248 | }, false);
249 |
250 | return true;
251 | }
252 | }
253 | return $ionicActionSheet.show(options);
254 | }
255 |
256 |
257 | // 提交回帖
258 | function saveReply() {
259 | if (vm.current_edit_reply) {
260 | TopicService.updateReply(vm.current_edit_reply.id, vm.reply_content)
261 | .then(function(result) {
262 | closeReplyModal();
263 | var idx = vm.replies.indexOf(vm.current_edit_reply);
264 | vm.replies[idx].body_html = result.reply.body_html;
265 | vm.current_edit_reply = null;
266 | vm.reply_content = '';
267 | });
268 | } else {
269 | TopicService.createReply($stateParams.topic_id, vm.reply_content)
270 | .then(function(result) {
271 | closeReplyModal();
272 | vm.replies.push(result.reply);
273 | vm.reply_content = "";
274 | }).catch(function(err) {
275 | BaseService.alert('提交回复', '', '提交失败!');
276 | })
277 | }
278 | }
279 |
280 | function loadMore() {
281 | vm.current_page++;
282 | var offset = ((vm.current_page || 0) - 1) * 20;
283 | return TopicService.getRepliesByTopic($stateParams.topic_id, offset)
284 | .then(function(result) {
285 | vm.has_more = result.replies && result.replies.length > 0;
286 | if (!vm.has_more) {
287 | vm.current_page--;
288 | } else {
289 | vm.replies = _.union(vm.replies, result.replies);
290 | vm.user_liked_reply_ids = _.union(vm.user_liked_reply_ids, result.meta.user_liked_reply_ids);
291 | $scope.$broadcast('scroll.infiniteScrollComplete');
292 | }
293 | });
294 | }
295 |
296 | function showReplies() {
297 | var pos = $ionicPosition.position(angular.element(document.getElementById('topic-stats')));
298 | $ionicScrollDelegate.scrollTo(0, pos.top, true);
299 | }
300 |
301 | $scope.$on('$ionicView.beforeEnter', function(viewInfo, state) {
302 | BaseService.statusBar(0);
303 | });
304 |
305 | $scope.$on('$ionicView.leave', function(viewInfo, state) {
306 | if (state.direction === "back") {
307 | BaseService.recycleModalById('reply-modal');
308 | }
309 | })
310 | }
311 |
312 | })();
313 |
--------------------------------------------------------------------------------
/www/js/controllers/topics.controller.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | 'use strict';
3 |
4 | angular
5 | .module('app.controller')
6 | .controller('TopicsController', TopicsController);
7 |
8 | ////////////////////////////////////////////////////////////
9 |
10 | /* @ngInject */
11 | function TopicsController($rootScope, $scope, $timeout,
12 | $stateParams, BaseService, AuthService, TopicService) {
13 |
14 | BaseService.statusBar(0);
15 |
16 | var vm = this;
17 | vm.topics = {};
18 | vm.is_logined = AuthService.isAuthencated();
19 | vm.current_page = 1; // 当前页码
20 | vm.has_new_notice = false;
21 |
22 | // Functions
23 | vm.doRefresh = doRefresh;
24 | vm.loadMore = loadMore;
25 |
26 | activate();
27 |
28 | function activate() {
29 | vm.current_page = 1;
30 |
31 | loadData($stateParams.node_id, $stateParams.type)
32 | .then(function(result) {
33 | vm.topics = result;
34 | });
35 | }
36 |
37 | function loadData(node_id, node_type, page) {
38 | var offset = ((page || 1) - 1) * 20;
39 | return TopicService.getTopics(node_id, node_type, offset)
40 | .then(function(result) {
41 | var topics = {};
42 | topics.type = $stateParams.type;
43 | topics.title = $stateParams.node_name;
44 | topics.items = result.topics;
45 | topics.header_template = result.header_template;
46 | return topics;
47 | })
48 | .catch(function(err) {
49 | return err;
50 | });
51 | }
52 |
53 | function doRefresh() {
54 | vm.current_page = 1;
55 | loadData($stateParams.node_id, $stateParams.type)
56 | .then(function(result) {
57 | vm.topics = result;
58 | $scope.$broadcast('scroll.refreshComplete');
59 | });
60 | }
61 |
62 | function loadMore() {
63 | vm.current_page++;
64 | return loadData($stateParams.node_id, $stateParams.type, vm.current_page)
65 | .then(function(result) {
66 | vm.has_more = result.items && result.items.length > 0;
67 | if (!vm.has_more) {
68 | vm.current_page--;
69 | } else {
70 | vm.topics.items = _.union(vm.topics.items, result.items);
71 | $scope.$broadcast('scroll.infiniteScrollComplete');
72 | }
73 | });
74 | }
75 |
76 | $scope.$on('$ionicView.beforeEnter', function(viewInfo, state) {
77 | BaseService.statusBar(0);
78 | doRefresh();
79 | });
80 |
81 | $scope.$on('new_topic_success', function() {
82 | doRefresh();
83 | });
84 | }
85 |
86 | })();
87 |
--------------------------------------------------------------------------------
/www/js/controllers/user.controller.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | 'use strict';
3 |
4 | angular
5 | .module('app.controller')
6 | .controller('UserController', UserController);
7 |
8 | ////////////////////////////////////////////////////////////
9 |
10 | /* @ngInject */
11 | function UserController($stateParams, $rootScope, $scope,
12 | $timeout, BaseService, AuthService, UserService) {
13 | var vm = this;
14 | vm.user = {}; // 所查看的用户
15 | vm.current_user = AuthService.getCurrentUser(); // 本人
16 | vm.is_follow = false;
17 | vm.is_block = false;
18 |
19 | // Functions
20 | vm.isSelf = isSelf;
21 | vm.toggleFollow = toggleFollow;
22 | vm.toggleBlock = toggleBlock;
23 | vm.openUrl = openUrl;
24 |
25 | activate();
26 |
27 | function activate() {
28 |
29 | return AuthService.getUserInfo($stateParams.login)
30 | .then(function(result) {
31 |
32 | vm.user = result.user;
33 | vm.is_follow = result.meta.followed;
34 | vm.is_block = result.meta.blocked;
35 | return vm.user;
36 | });
37 | }
38 |
39 | function isSelf() {
40 | return !!vm.current_user &&
41 | vm.current_user.login === $stateParams.login;
42 | }
43 |
44 | function toggleFollow() {
45 | if (!vm.current_user) {
46 | BaseService.showModal('login-modal');
47 | return;
48 | }
49 | var follow = vm.is_follow ? 'unfollow' : 'follow';
50 | return UserService.userAction($stateParams.login, follow)
51 | .then(function(result) {
52 | vm.is_follow ? vm.user.followers_count-- : vm.user.followers_count++;
53 | vm.is_follow = !vm.is_follow;
54 | });
55 | }
56 |
57 | function toggleBlock() {
58 | if (!vm.current_user) {
59 | BaseService.showModal('login-modal');
60 | return;
61 | }
62 | var block = vm.is_block ? 'unblock' : 'block';
63 | return UserService.userAction($stateParams.login, block)
64 | .then(function(result) {
65 | vm.is_block = !vm.is_block;
66 | });
67 | }
68 |
69 | function openUrl(url) {
70 | BaseService.openUrl(url);
71 | }
72 |
73 | $scope.$on('$ionicView.beforeEnter', function(viewInfo, state) {
74 | BaseService.statusBar(0);
75 | });
76 | }
77 |
78 | })();
79 |
--------------------------------------------------------------------------------
/www/js/core/config.core.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | 'use strict';
3 |
4 | angular
5 | .module('app.core')
6 | .config(oauthConfig)
7 | // .config(oauthConfigDevelopment)
8 | .config(backButtonConfig)
9 | .config(httpConfig)
10 | .config(jsScrolling)
11 | .constant('rbchina_api', {
12 | url_prefix: "https://ruby-china.org/api/v3"
13 | // url_prefix: "http://localhost:3000/api/v3"
14 | });
15 |
16 | ////////////////////////////////////////////////////////////
17 |
18 | function httpConfig($httpProvider) {
19 | $httpProvider.interceptors.push(function($rootScope) {
20 | return {
21 | request: function(config) {
22 | $rootScope.$broadcast('loading:show');
23 | return config;
24 | },
25 | response: function(response) {
26 | $rootScope.$broadcast('loading:hide');
27 | return response;
28 | },
29 |
30 | responseError: function(response) {
31 | $rootScope.$broadcast('loading:hide');
32 | if (response.status == 401) {
33 | $rootScope.$broadcast('relogin');
34 | console.log('access_token is invalid, status', 401);
35 | }
36 | return response;
37 | }
38 | }
39 | })
40 | }
41 |
42 | /* @ngInject */
43 | function oauthConfig(OAuthProvider) {
44 | OAuthProvider.configure({
45 | baseUrl: 'https://ruby-china.org',
46 | grantPath: '/oauth/token',
47 | revokePath: '/oauth/revoke',
48 | clientId: '1c58e228',
49 | clientSecret: '6d2c9cbef3e4baa56e1cf1d0db41d213105221aeff01281ac7009d21af810c58'
50 | });
51 | }
52 |
53 | function oauthConfigDevelopment(OAuthProvider) {
54 | OAuthProvider.configure({
55 | baseUrl: 'http://localhost:3000',
56 | grantPath: '/oauth/token',
57 | revokePath: '/oauth/revoke',
58 | clientId: '1fc177e0',
59 | clientSecret: '6259c0829ff85e06e9fc41460a429380da5f53ec9bf29a5d6742e9504819a1a3'
60 | });
61 | }
62 |
63 | /* @ngInject */
64 | function backButtonConfig($ionicConfigProvider) {
65 | $ionicConfigProvider.backButton.text('').icon('mdi mdi-arrow-left');
66 | }
67 |
68 | /* @ngInject */
69 | function jsScrolling($ionicConfigProvider) {
70 | if (!ionic.Platform.isIOS()) {
71 | $ionicConfigProvider.scrolling.jsScrolling(false);
72 | }
73 | }
74 | })();
75 |
--------------------------------------------------------------------------------
/www/js/core/core.module.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | 'use strict';
3 |
4 | angular
5 | .module('app.core', [
6 | // Ionic modules
7 | 'ionic', 'ngCordova', 'ui.router',
8 | // Vendors
9 | 'angularMoment', 'angular-oauth2',
10 | 'ngFileUpload', 'templates'
11 | ]);
12 |
13 | })();
14 |
--------------------------------------------------------------------------------
/www/js/core/route.core.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | 'use strict';
3 |
4 | angular
5 | .module('app.core')
6 | .config(routeConfig);
7 |
8 | ////////////////////////////////////////////////////////////
9 |
10 | /* @ngInject */
11 | function routeConfig($stateProvider, $urlRouterProvider) {
12 | $stateProvider
13 | .state('app', {
14 | url: '/app',
15 | abstract: true,
16 | templateUrl: 'menu.html',
17 | controller: 'MainController as vm'
18 | })
19 | .state('app.topics', {
20 | url: '/topics/:type',
21 | views: {
22 | 'menuContent': {
23 | templateUrl: 'topics.html',
24 | controller: 'TopicsController as vm'
25 | }
26 | }
27 | })
28 | .state('app.jobs', {
29 | url: '/jobs',
30 | params: {
31 | node_id: '25', // 社区招聘的ID是25
32 | node_name: '招聘'
33 | },
34 | views: {
35 | 'menuContent': {
36 | templateUrl: 'topics.html',
37 | controller: 'TopicsController as vm'
38 | }
39 | }
40 | })
41 | .state('app.rbdev', {
42 | url: '/rbdev',
43 | params: {
44 | node_id: '23', // 社区开发的ID是23
45 | node_name: '社区开发'
46 | },
47 | views: {
48 | 'menuContent': {
49 | templateUrl: 'topics.html',
50 | controller: 'TopicsController as vm'
51 | }
52 | }
53 | })
54 | .state('app.nopoint', {
55 | url: '/nopoint',
56 | params: {
57 | node_id: '61', // NoPoint的ID是61
58 | node_name: 'NoPoint'
59 | },
60 | views: {
61 | 'menuContent': {
62 | templateUrl: 'topics.html',
63 | controller: 'TopicsController as vm'
64 | }
65 | }
66 | })
67 | .state('app.topic', {
68 | url: '/topic/:topic_id',
69 | params: {
70 | replies_count: null
71 | },
72 | views: {
73 | 'menuContent': {
74 | templateUrl: 'topic.html',
75 | controller: 'TopicController as vm'
76 | }
77 | }
78 | })
79 | .state('app.user', {
80 | url: '/user/:login',
81 | views: {
82 | 'menuContent': {
83 | templateUrl: 'user/profile.html',
84 | controller: 'UserController as vm'
85 | }
86 | }
87 | })
88 | .state('app.notification', {
89 | url: '/notifications',
90 | views: {
91 | 'menuContent': {
92 | templateUrl: 'notifications.html',
93 | controller: 'NotificationsController as vm'
94 | }
95 | }
96 | });
97 | // if none of the above states are matched, use this as the fallback
98 | $urlRouterProvider.otherwise('/app/topics/last_actived');
99 | }
100 |
101 | })();
102 |
--------------------------------------------------------------------------------
/www/js/core/run.core.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | 'use strict';
3 |
4 | angular
5 | .module('app.core')
6 | .run(ionicRun)
7 | .run(oauthRun)
8 | .run(openUrl);
9 |
10 | ////////////////////////////////////////////////////////////
11 |
12 | /* @ngInject */
13 | function ionicRun($rootScope, $ionicPlatform, $window, $state, amMoment) {
14 | $ionicPlatform.ready(function() {
15 | // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
16 | // for form inputs)
17 | if (window.cordova && window.cordova.plugins.Keyboard) {
18 | cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
19 | cordova.plugins.Keyboard.disableScroll(true);
20 | }
21 | if (window.StatusBar) {
22 | // org.apache.cordova.statusbar required
23 | StatusBar.styleLightContent();
24 | }
25 | window.addEventListener('native.keyboardshow', function(event) {
26 | $rootScope.keyboardHeight = event.keyboardHeight;
27 | });
28 | })
29 |
30 | amMoment.changeLocale('zh-cn');
31 | }
32 |
33 | /* @ngInject */
34 | function oauthRun($rootScope, $window, OAuth) {
35 | $rootScope.$on('oauth:error', function(event, rejection) {
36 | // Ignore `invalid_grant` error - should be catched on `LoginController`.
37 | if ('invalid_grant' === rejection.data.error) {
38 | return;
39 | }
40 |
41 | // Refresh token when a `invalid_token` error occurs.
42 | if ('invalid_token' === rejection.data.error) {
43 | return OAuth.getRefreshToken();
44 | }
45 |
46 | // Redirect to `/login` with the `error_reason`.
47 | return $window.location.href = '/login?error_reason=' + rejection.data.error;
48 | });
49 | }
50 |
51 | /* @ngInject */
52 | function openUrl($window, BaseService) {
53 | $window.openUrl = BaseService.openUrl;
54 | }
55 |
56 | })();
57 |
--------------------------------------------------------------------------------
/www/js/filters/exlink.filter.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | 'use strict';
3 |
4 | angular
5 | .module('app.filter')
6 | .filter('externalLinks', externalLinks);
7 |
8 | /* @ngInject */
9 | function externalLinks($sce) {
10 | return function(text) {
11 | // 说明:由于删除 jQuery 的缘故,不再使用 BaseService.formatTopicBody 方法调整链接
12 | var exlinks = /href="((http|https):\/\/[\S]+)"/gi,
13 | atuser_links = /href="(\/[\S]+)"/gi,
14 | atfloor_links = /href="(#reply[0-9]+)"/gi,
15 | output = "";
16 |
17 | if (text.match(exlinks)) {
18 | output = $sce.trustAsHtml(
19 | text.replace(exlinks, "onClick=\"openUrl('$1')\"")
20 | );
21 | } else if (text.match(atuser_links)) {
22 | output = $sce.trustAsHtml(
23 | text.replace(atuser_links, "href=\"#/app/user$1\"")
24 | );
25 | } else if (text.match(atfloor_links)) {
26 | output = $sce.trustAsHtml(
27 | text.replace(atfloor_links, "")
28 | );
29 | } else {
30 | return text;
31 | }
32 | // console.debug(output.toString());
33 | return output;
34 | }
35 | }
36 | })();
37 |
--------------------------------------------------------------------------------
/www/js/filters/filter.module.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | 'use strict';
3 |
4 | angular
5 | .module('app.filter', [])
6 |
7 | })();
8 |
--------------------------------------------------------------------------------
/www/js/services/auth.service.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | 'use strict';
3 |
4 | angular
5 | .module('app.service')
6 | .factory('AuthService', AuthService);
7 |
8 | ////////////////////////////////////////////////////////////
9 |
10 | /* @ngInject */
11 | function AuthService($q, $http, $window, OAuth, rbchina_api) {
12 | var LOCAL_TOKEN_KEY;
13 | var authToken;
14 |
15 | var service = {
16 | login: login,
17 | logout: logout,
18 | getUserInfo: getUserInfo,
19 | getAccessToken: getAccessToken,
20 | refreshAccessToken: refreshAccessToken,
21 | isAuthencated: isAuthencated,
22 | getCurrentUser: getCurrentUser,
23 | submitDeviceToken: submitDeviceToken
24 | };
25 |
26 | // 载入用户登录信息
27 | loadUserCredentials();
28 |
29 | return service;
30 |
31 | // 加载用户验证信息
32 | function loadUserCredentials() {
33 | var token = getAccessToken();
34 | if (token) {
35 | useCredentials(token);
36 | }
37 | }
38 |
39 | // 存储用户验证信息
40 | function storeUserCredentials(token) {
41 | useCredentials(token);
42 | }
43 |
44 | // 激活用户验证
45 | function useCredentials(token) {
46 | authToken = token;
47 | $window.localStorage['access_token'] = token;
48 | // Set the token as header for your requests!
49 | $http.defaults.headers.common['Authorization'] = "Bearer " + token;
50 | }
51 |
52 | // 销毁用户验证
53 | function destroyUserCredentials() {
54 | authToken = undefined;
55 | $http.defaults.headers.common['Authorization'] = undefined;
56 | OAuth.revokeToken();
57 | $window.localStorage['access_token'] = null;
58 | $window.localStorage['current_user'] = null;
59 | $window.localStorage['auth_info'] = null;
60 | setCurrentUser({});
61 | }
62 |
63 | function getUserInfo(login) {
64 | var q = $q.defer();
65 | var url = rbchina_api.url_prefix + '/users/' + login + '.json';
66 | $http.get(url, {
67 | params: {
68 | access_token: authToken
69 | }
70 | })
71 | .success(function(result) {
72 | q.resolve(result);
73 | }).error(function(err) {
74 | q.reject(err);
75 | });
76 | return q.promise;
77 | }
78 |
79 | function setCurrentUser(user) {
80 | $window.localStorage['current_user'] = JSON.stringify(user);
81 | }
82 |
83 | function getCurrentUser() {
84 | var info = $window.localStorage['current_user'];
85 | if (!info) {
86 | return null
87 | }
88 | return JSON.parse(info);
89 | }
90 |
91 | function submitDeviceToken(token) {
92 | var q = $q.defer();
93 |
94 | // 如果有传 Token,记录到 localStorage
95 | if (token != undefined) {
96 | $window.localStorage['device_token'] = token;
97 | }
98 |
99 | if (!isAuthencated()) {
100 | return q.promise;
101 | }
102 |
103 | var deviceToken = $window.localStorage['device_token'];
104 | if (deviceToken === undefined) {
105 | return q.promise;
106 | }
107 |
108 | var params = {
109 | platform: 'ios',
110 | token: deviceToken
111 | };
112 | var url = rbchina_api.url_prefix + '/devices.json';
113 | $http.post(url, params).success(function(result) {
114 | q.resolve(result);
115 | }).error(function(err) {
116 | q.reject(err);
117 | });
118 | return q.promise;
119 | }
120 |
121 | function login(user) {
122 | var q = $q.defer();
123 | if (!user.username) {
124 | q.reject("用户名或 Email 没有填写");
125 | return q.promise;
126 | }
127 |
128 | if (!user.password) {
129 | q.reject("还没未填写密码");
130 | return q.promise;
131 | }
132 |
133 |
134 | OAuth.getAccessToken(user)
135 | .then(function(result) {
136 | if (result.status == 200) {
137 | $window.localStorage['auth_info'] = JSON.stringify(user);
138 | storeUserCredentials(result.data.access_token);
139 |
140 | // 获取用户信息并存储
141 | getUserInfo('me')
142 | .then(function(response) {
143 | // 输出用户信息
144 | setCurrentUser(response.user);
145 |
146 | submitDeviceToken().then(function() { });
147 | q.resolve(response.user);
148 | }).catch(function(error) {
149 | q.reject(error);
150 | });
151 | } else if (result.status == 401) {
152 | q.reject("对不起,用户名或密码错误!");
153 | } else {
154 | q.reject("未知异常,登陆失败,请稍后再重试。")
155 | }
156 | }).catch(function(err) {
157 | q.reject("对不起,用户名或密码错误!");
158 | });
159 | return q.promise;
160 | }
161 |
162 | function logout() {
163 | destroyUserCredentials();
164 | }
165 |
166 | function isAuthencated() {
167 | return !!authToken && getCurrentUser().login;
168 | }
169 |
170 | function getAccessToken() {
171 | return authToken || $window.localStorage['access_token'] || null;
172 | }
173 |
174 | function refreshAccessToken() {
175 | var q = $q.defer();
176 | var info = $window.localStorage['auth_info'] || '{}';
177 | var user = JSON.parse(info) || {};
178 | if (!user.username || !user.password) {
179 | console.warn('There is not user login info stored');
180 | q.reject("No auth info")
181 | return q.promise;
182 | }
183 |
184 | return login(user);
185 | }
186 | }
187 |
188 | })();
189 |
--------------------------------------------------------------------------------
/www/js/services/base.service.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | 'use strict';
3 |
4 | angular
5 | .module('app.service')
6 | .factory('BaseService', BaseService);
7 |
8 | ////////////////////////////////////////////////////////////
9 |
10 | /* @ngInject */
11 | function BaseService($q, $http, $ionicLoading, $ionicPopup,
12 | $ionicModal, $ionicActionSheet, $timeout, $cordovaInAppBrowser, AuthService, rbchina_api) {
13 |
14 | var modals = [];
15 | var statusBarStyle = 0;
16 | var service = {
17 | // 弹出框
18 | alert: alert,
19 | confirm: confirm,
20 | // 加载动画
21 | showLoading: showLoading,
22 | hideLoading: hideLoading,
23 | // 模态框
24 | registModal: registModal,
25 | showModal: showModal,
26 | hideModal: hideModal,
27 | recycleModals: recycleModals,
28 | recycleModalById: recycleModalById,
29 | reserveModalById: reserveModalById,
30 | // ActionSheet
31 | showActionSheet: showActionSheet,
32 | // 上传图片
33 | uploadPicture: uploadPicture,
34 | openUrl: openUrl,
35 | dismissSafari: dismissSafari,
36 | statusBar: statusBar,
37 | formatTopicBody: formatTopicBody
38 | };
39 |
40 | return service;
41 |
42 | //////////////////////////////////////////////////////////////////////
43 | // 说明:由于删除 jQuery 的缘故,不再使用 BaseService.formatTopicBody 方法调整链接
44 | function formatTopicBody() {
45 | $timeout(function() {
46 | // 处理外部链接
47 | var exlinks = $('.ex-link');
48 |
49 | // 先去掉 href 属性,防止触发内部浏览器
50 | _.forEach(exlinks, function(link) {
51 | var orig = $(link).attr("href");
52 | $(link).removeAttr("href");
53 | $(link).data('url', orig);
54 | // $(link).attr("ng-click", "vm.openExternLinks('" + orig + "')");
55 | });
56 |
57 | exlinks.click(function() {
58 | var url = $(this).data('url');
59 | openUrl(url);
60 | return false;
61 | });
62 |
63 | // 处理@链接
64 | var atuser_links = $('.at_user');
65 | _.forEach(atuser_links, function(link) {
66 | var orig = $(link).attr("href") || '';
67 | if (orig.indexOf('#/app/user/') == -1) {
68 | $(link).attr("href", "#/app/user/" + orig.slice(1));
69 | }
70 | });
71 |
72 | var atfloor_links = $('.at_floor');
73 | atfloor_links.on('click', function() {
74 | return false;
75 | });
76 | });
77 | }
78 |
79 | // 弹出警告框
80 | function alert(title, subTitle, message) {
81 | return $ionicPopup.alert({
82 | title: title,
83 | subTitle: subTitle,
84 | template: '' + message + '
',
85 | okText: '知道了'
86 | });
87 | }
88 |
89 | // 弹出确认框
90 | function confirm(title, subTitle, message) {
91 | return $ionicPopup.confirm({
92 | title: title,
93 | subTitle: subTitle,
94 | template: '' + message + '
',
95 | okText: '确认',
96 | cancelText: '取消'
97 | })
98 | .then(function(res) {
99 | return res;
100 | });
101 | }
102 |
103 | // 弹出加载界面
104 | // 可传入Spinner类型和消息
105 | function showLoading(style, message) {
106 | return $ionicLoading.show({
107 | template: '' +
109 | message + '
',
110 | duration: 6000 // 为避免卡死,6秒后如无反应则隐藏
111 | });
112 | }
113 |
114 | // 结束加载动画
115 | function hideLoading() {
116 | $ionicLoading.hide();
117 | }
118 |
119 | // 注册模态框
120 | function registModal(template_url, modal_id, scope, opts) {
121 | var defaults = {
122 | scope: scope,
123 | animation: 'slide-in-up'
124 | };
125 | var options = _.merge(defaults, opts);
126 | return $ionicModal.fromTemplateUrl(template_url, options)
127 | .then(function(modal) {
128 | if (_.indexOf(_.pluck(modals, "id"), modal_id) === -1) {
129 | modals.push({
130 | id: modal_id,
131 | modal: modal
132 | });
133 | return modals;
134 | }
135 | });
136 | }
137 |
138 | // 弹出模态框
139 | function showModal(modal_id) {
140 | changeStatusBar(1);
141 | var modal = _.find(modals, "id", modal_id).modal;
142 | return modal.show();
143 | }
144 |
145 | // 隐藏模态框
146 | function hideModal(modal_id) {
147 | statusBar(statusBarStyle);
148 | var modal = _.find(modals, "id", modal_id).modal;
149 | return modal.hide();
150 | }
151 |
152 | // 回收所有模态框
153 | function recycleModals() {
154 | _.forEach(modals, function(modal) {
155 | modal.modal.remove();
156 | });
157 | modals = [];
158 | }
159 |
160 | // 回收某个模态框
161 | function recycleModalById(modal_id) {
162 | var modal = _.find(modals, "id", modal_id).modal;
163 | modal.remove();
164 | modals = _.reject(modals, "id", modal_id);
165 | }
166 |
167 | // 保留某个模态框
168 | function reserveModalById(modal_id) {
169 | var modal = _.find(modals, "id", modal_id).modal;
170 | _.forEach(modals, function(m) {
171 | if (modal.id !== m.modal.id) {
172 | m.modal.remove();
173 | }
174 | });
175 | modals = _.select(modals, "id", modal_id);
176 | }
177 |
178 | // 弹出 ActionSheet
179 | function showActionSheet(buttons, titleText, cancelText, buttonsCb, destructiveText, destructiveCb) {
180 | var options = {
181 | buttons: buttons,
182 | titleText: titleText,
183 | cancelText: cancelText,
184 | buttonClicked: buttonsCb,
185 | destructiveText: destructiveText,
186 | destructiveButtonClicked: destructiveCb
187 | };
188 | return $ionicActionSheet.show(options);
189 | }
190 |
191 | // 上传图片
192 | function uploadPicture(file) {
193 | var q = $q.defer();
194 | var url = rbchina_api.url_prefix + '/photos.json';
195 | showLoading('lines', '上传中...');
196 | var data = new FormData();
197 | var ext = file.split(',')[0].split(':')[1].split(';')[0].split('/')[1];
198 | data.append("file", dataURItoBlob(file), "photo." + ext); // 调了半天原来是这里Blob要加个name
199 | $http.post(url, data, {
200 | params: {
201 | access_token: AuthService.getAccessToken()
202 | },
203 | transformRequest: angular.identity,
204 | headers: {
205 | 'Content-Type': undefined
206 | }
207 | })
208 | .success(function(result) {
209 | hideLoading();
210 | q.resolve(result);
211 | })
212 | .error(function(err) {
213 | hideLoading();
214 | q.reject(err);
215 | });
216 | return q.promise;
217 | }
218 |
219 | // https://github.com/EddyVerbruggen/cordova-plugin-safariviewcontroller
220 | function openUrl(url) {
221 | // console.debug(url);
222 | url = encodeURI(url);
223 |
224 | SafariViewController.isAvailable(function(available) {
225 | if (available) {
226 | SafariViewController.show({
227 | url: url,
228 | animated: false, // default true, note that 'hide' will reuse this preference (the 'Done' button will always animate though)
229 | enterReaderModeIfAvailable: false // default false
230 | },
231 | // this success handler will be invoked for the lifecycle events 'opened', 'loaded' and 'closed'
232 | function(result) {},
233 | function(msg) {})
234 | } else {
235 | // potentially powered by InAppBrowser because that (currently) clobbers window.open
236 | var options = {
237 | location: 'yes',
238 | clearcache: 'yes',
239 | toolbar: 'yes'
240 | };
241 | $cordovaInAppBrowser.open(url, '_blank', options)
242 | .then(function(event) {
243 | // success
244 | })
245 | .catch(function(event) {
246 | // error
247 | });
248 | }
249 | })
250 | }
251 |
252 | function dismissSafari() {
253 | SafariViewController.hide();
254 | }
255 |
256 | function statusBar(style) {
257 | statusBarStyle = style;
258 | changeStatusBar(style);
259 | }
260 |
261 | function changeStatusBar(style) {
262 | if (!window.StatusBar) {
263 | return;
264 | }
265 |
266 | if (style == 0) {
267 | StatusBar.styleLightContent();
268 | } else {
269 | StatusBar.styleDefault();
270 | }
271 | }
272 | }
273 |
274 | // base64字符串转图片格式
275 | function dataURItoBlob(dataURI) {
276 | // convert base64/URLEncoded data component to raw binary data held in a string
277 | var byteString;
278 | if (dataURI.split(',')[0].indexOf('base64') >= 0)
279 | byteString = atob(dataURI.split(',')[1]);
280 | else
281 | byteString = unescape(dataURI.split(',')[1]);
282 |
283 | // separate out the mime component
284 | var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
285 |
286 | // write the bytes of the string to a typed array
287 | var ia = new Uint8Array(byteString.length);
288 | for (var i = 0; i < byteString.length; i++) {
289 | ia[i] = byteString.charCodeAt(i);
290 | }
291 | return new Blob([ia], {
292 | name: 'photo',
293 | type: mimeString
294 | });
295 | }
296 |
297 | })();
298 |
--------------------------------------------------------------------------------
/www/js/services/camera.service.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | 'use strict';
3 |
4 | angular
5 | .module('app.service')
6 | .factory('CameraService', CameraService);
7 |
8 | //////////////////////////////////////////////////////////////////////
9 |
10 | /* @ngInject */
11 | function CameraService($q) {
12 | var service = {
13 | getPicture: getPicture
14 | };
15 |
16 | return service;
17 |
18 | //////////////////////////////////////////////////////////////////////
19 |
20 | // 获取照片
21 | function getPicture(source, size, type) {
22 | var q = $q.defer();
23 | var options = {
24 | quality: 75,
25 | destinationType: type,
26 | sourceType: source,
27 | allowEdit: true,
28 | encodingType: Camera.EncodingType.JPEG,
29 | targetWidth: size.width,
30 | targetHeight: size.height,
31 | popoverOptions: CameraPopoverOptions, /* jshint ignore:line */
32 | saveToPhotoAlbum: false,
33 | correctOrientation: false
34 | };
35 |
36 | navigator.camera.getPicture(function(imageData) {
37 | q.resolve("data:image/jpeg;base64," + imageData);
38 | }, function(err) {
39 | q.reject("'----- Failed because: ' + message");
40 | }, options);
41 |
42 | return q.promise;
43 | }
44 | }
45 | })();
46 |
--------------------------------------------------------------------------------
/www/js/services/service.module.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | 'use strict';
3 |
4 | angular
5 | .module('app.service', []);
6 |
7 | })();
8 |
--------------------------------------------------------------------------------
/www/js/services/topic.service.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | 'use strict';
3 |
4 | angular
5 | .module('app.service')
6 | .factory('TopicService', TopicService);
7 |
8 | ////////////////////////////////////////////////////////////
9 |
10 | /* @ngInject */
11 | function TopicService($q, $http, AuthService, rbchina_api) {
12 | // 根据不同节点在首页显示不同的Header
13 | var topics_headers = [{
14 | node_id: undefined,
15 | header_template: 'templates/topics/_filters.html'
16 | }];
17 | var service = {
18 | getTopics: getTopics,
19 | getTopic: getTopic,
20 | getTopicWithReplies: getTopicWithReplies,
21 | getRepliesByTopic: getRepliesByTopic,
22 | createReply: createReply,
23 | getReply: getReply,
24 | updateReply: updateReply,
25 | destroyReply: destroyReply,
26 | getAllNodes: getAllNodes,
27 | createTopic: createTopic,
28 | likeTopic: likeTopic,
29 | unlikeTopic: unlikeTopic,
30 | like: like,
31 | favorite: favorite,
32 | follow: follow,
33 | ban: ban,
34 | destroy: destroy
35 | };
36 |
37 | return service;
38 |
39 | function getTopics(node_id, type, offset) {
40 | var q = $q.defer();
41 | var url = rbchina_api.url_prefix + '/topics.json';
42 | $http.get(url, {
43 | params: {
44 | node_id: node_id,
45 | type: type,
46 | offset: offset,
47 | limit: 20
48 | }
49 | })
50 | .success(function(result) {
51 | result.header_template = _.result(_.findWhere(topics_headers, {
52 | node_id: node_id
53 | }), 'header_template');
54 | q.resolve(result);
55 | }).error(function(err) {
56 | q.reject(err);
57 | });
58 | return q.promise;
59 | }
60 |
61 | function getTopic(topic_id) {
62 | var q = $q.defer();
63 | var url = rbchina_api.url_prefix + '/topics/' + topic_id + '.json';
64 | $http.get(url).success(function(result) {
65 | q.resolve(result);
66 | }).error(function(err) {
67 | q.reject(err);
68 | });
69 | return q.promise;
70 | }
71 |
72 | function like(able_type, able_id, liked) {
73 | var q = $q.defer();
74 | var url = rbchina_api.url_prefix + '/likes.json?obj_type=' + able_type + '&obj_id=' + able_id;
75 | var method = liked == true ? 'DELETE' : 'POST';
76 |
77 | $http({
78 | method: method,
79 | url: url
80 | }).success(function(result) {
81 | q.resolve(result);
82 | }).error(function(err) {
83 | q.reject(err);
84 | });
85 | return q.promise;
86 | }
87 |
88 | function likeTopic(topic_id) {
89 | var q = $q.defer();
90 | var url = rbchina_api.url_prefix + '/likes.json';
91 | var params = {
92 | obj_type: 'topic',
93 | obj_id: topic_id,
94 | access_token: AuthService.getAccessToken()
95 | };
96 |
97 | $http.post(url, params).success(function(result) {
98 | q.resolve(result);
99 | }).error(function(err) {
100 | q.reject(err);
101 | });
102 | return q.promise;
103 | }
104 |
105 | function unlikeTopic(topic_id) {
106 | var q = $q.defer();
107 | var url = rbchina_api.url_prefix + '/likes.json?obj_type=topic&obj_id=' + topic_id;
108 |
109 | $http.delete(url).success(function(result) {
110 | q.resolve(result);
111 | }).error(function(err) {
112 | q.reject(err);
113 | });
114 | return q.promise;
115 | }
116 |
117 | function favorite(topic_id, favorited) {
118 | var q = $q.defer();
119 | var method = favorited == true ? 'unfavorite' : 'favorite';
120 | var url = rbchina_api.url_prefix + '/topics/' + topic_id + '/'+ method +'.json';
121 | $http.post(url).success(function(result) {
122 | q.resolve(result);
123 | }).error(function(err) {
124 | q.reject(err);
125 | });
126 | return q.promise;
127 | }
128 |
129 | function follow(topic_id, followd) {
130 | var q = $q.defer();
131 | var method = followd == true ? 'unfollow' : 'follow';
132 | var url = rbchina_api.url_prefix + '/topics/' + topic_id + '/' + method + '.json';
133 | $http.post(url).success(function(result) {
134 | q.resolve(result);
135 | }).error(function(err) {
136 | q.reject(err);
137 | });
138 | return q.promise;
139 | }
140 |
141 | function ban(topic_id) {
142 | var q = $q.defer();
143 | var url = rbchina_api.url_prefix + '/topics/' + topic_id + '/ban.json';
144 | $http.post(url).success(function(result) {
145 | q.resolve(result);
146 | }).error(function(err) {
147 | q.reject(err);
148 | });
149 | return q.promise;
150 | }
151 |
152 | function getTopicWithReplies(topic_id) {
153 | var q = $q.defer();
154 | getTopic(topic_id)
155 | .then(function(result) {
156 | var topic = result;
157 | var url = rbchina_api.url_prefix + '/topics/' + topic_id + '/replies.json';
158 | $http.get(url)
159 | .success(function(response) {
160 | topic.replies = response.replies;
161 | topic.user_liked_reply_ids = response.meta.user_liked_reply_ids;
162 | q.resolve(topic);
163 | }).error(function(e) {
164 | q.reject(e);
165 | });
166 | });
167 | return q.promise;
168 | }
169 |
170 | function getRepliesByTopic(topic_id, offset) {
171 | var q = $q.defer();
172 | var url = rbchina_api.url_prefix + '/topics/' + topic_id + '/replies.json';
173 | $http.get(url, {
174 | params: {
175 | offset: offset,
176 | limit: 150
177 | }
178 | })
179 | .success(function(result) {
180 | q.resolve(result);
181 | }).error(function(e) {
182 | q.reject(e);
183 | });
184 | return q.promise;
185 | }
186 |
187 | function getReply(reply_id) {
188 | var q = $q.defer();
189 | var url = rbchina_api.url_prefix + '/replies/' + reply_id + '.json';
190 |
191 | $http.get(url)
192 | .success(function(result) {
193 | q.resolve(result);
194 | }).error(function(err) {
195 | q.reject(err);
196 | });
197 | return q.promise;
198 | }
199 |
200 | // 提交回复
201 | function createReply(topic_id, body) {
202 | var q = $q.defer();
203 | var url = rbchina_api.url_prefix + '/topics/' + topic_id + '/replies.json';
204 | var data = {
205 | body: body,
206 | access_token: AuthService.getAccessToken()
207 | };
208 | $http.post(url, data)
209 | .success(function(result) {
210 | q.resolve(result);
211 | }).error(function(err) {
212 | q.reject(err);
213 | });
214 | return q.promise;
215 | }
216 |
217 | function updateReply(reply_id, body) {
218 | var q = $q.defer();
219 | var url = rbchina_api.url_prefix + '/replies/' + reply_id + '.json';
220 |
221 | $http.post(url, { body: body })
222 | .success(function(result) {
223 | q.resolve(result);
224 | }).error(function(err) {
225 | q.reject(err);
226 | });
227 | return q.promise;
228 | }
229 |
230 | function destroyReply(reply_id) {
231 | var q = $q.defer();
232 | var url = rbchina_api.url_prefix + '/replies/' + reply_id + '.json';
233 |
234 | $http.delete(url)
235 | .success(function(result) {
236 | q.resolve(result);
237 | }).error(function(err) {
238 | q.reject(err);
239 | });
240 | return q.promise;
241 | }
242 |
243 | // 获取所有节点名称
244 | function getAllNodes() {
245 | var q = $q.defer();
246 | var url = rbchina_api.url_prefix + '/nodes.json';
247 | $http.get(url)
248 | .success(function(result) {
249 | q.resolve(result);
250 | }).error(function(err) {
251 | q.reject(err);
252 | });
253 | return q.promise;
254 | }
255 |
256 | // 创建话题
257 | function createTopic(title, body, node_id) {
258 | var q = $q.defer();
259 | var url = rbchina_api.url_prefix + '/topics.json';
260 | var data = {
261 | title: title,
262 | body: body,
263 | node_id: node_id,
264 | access_token: AuthService.getAccessToken()
265 | };
266 | $http.post(url, data)
267 | .success(function(result) {
268 | q.resolve(result);
269 | }).error(function(err) {
270 | q.reject(err);
271 | });
272 | return q.promise;
273 | }
274 |
275 | function destroy(topic_id) {
276 | var q = $q.defer();
277 | var url = rbchina_api.url_prefix + '/topics/' + topic_id + '.json';
278 | $http.delete(url).success(function(result) {
279 | q.resolve(result);
280 | }).error(function(err) {
281 | q.reject(err);
282 | });
283 | return q.promise;
284 | }
285 |
286 | }
287 |
288 | })();
289 |
--------------------------------------------------------------------------------
/www/js/services/user.service.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | 'use strict';
3 |
4 | angular
5 | .module('app.service')
6 | .factory('UserService', UserService);
7 |
8 | ////////////////////////////////////////////////////////////
9 |
10 | /* @ngInject */
11 | function UserService($q, $http, AuthService, rbchina_api) {
12 | var service = {
13 | getUserTopics: getUserTopics,
14 | getUnreadNotificationsCount: getUnreadNotificationsCount,
15 | getUserNotifications: getUserNotifications,
16 | markNotificationsRead: markNotificationsRead,
17 | deleteAllNotifications: deleteAllNotifications,
18 | userAction: userAction
19 | };
20 |
21 | return service;
22 |
23 |
24 | // 获取用户创建列表
25 | function getUserTopics(login) {
26 | var q = $q.defer();
27 | var url = rbchina_api.url_prefix + '/users/' + login + '/topics.json';
28 | $http.get(url)
29 | .success(function(result) {
30 | q.resolve(result);
31 | }).error(function(err) {
32 | q.reject(err);
33 | });
34 | return q.promise;
35 | }
36 |
37 | function getUnreadNotificationsCount() {
38 | var q = $q.defer();
39 | var url = rbchina_api.url_prefix + '/notifications/unread_count.json';
40 | $http.get(url)
41 | .success(function(result) {
42 | q.resolve(result);
43 | }).error(function(err) {
44 | q.reject(err);
45 | });
46 | return q.promise;
47 | }
48 |
49 | // 获取用户通知列表
50 | function getUserNotifications(offset) {
51 | var q = $q.defer();
52 | var url = rbchina_api.url_prefix + '/notifications.json';
53 | $http.get(url, {
54 | params: {
55 | offset: offset,
56 | access_token: AuthService.getAccessToken()
57 | }
58 | })
59 | .success(function(result) {
60 | q.resolve(result.notifications);
61 | }).error(function(err) {
62 | q.reject(err);
63 | });
64 | return q.promise;
65 | }
66 |
67 | function markNotificationsRead(ids) {
68 | var q = $q.defer();
69 | var url = rbchina_api.url_prefix + '/notifications/read.json';
70 | $http.post(url, {
71 | ids: ids
72 | })
73 | .success(function(result) {
74 | q.resolve(result.notifications);
75 | }).error(function(err) {
76 | q.reject(err);
77 | });
78 | return q.promise;
79 | }
80 |
81 | function deleteAllNotifications(ids) {
82 | var q = $q.defer();
83 | var url = rbchina_api.url_prefix + '/notifications/all.json';
84 | $http.delete(url).success(function(result) {
85 | q.resolve(result);
86 | }).error(function(err) {
87 | q.reject(err);
88 | });
89 | return q.promise;
90 | }
91 |
92 |
93 | // 关注或屏蔽用户
94 | // action: follow-关注;block-屏蔽
95 | function userAction(login, action) {
96 | var q = $q.defer();
97 | var url = rbchina_api.url_prefix + '/users/' + login + '/' + action + '.json';
98 | var data = {
99 | login: login,
100 | access_token: AuthService.getAccessToken()
101 | }
102 | $http.post(url, data)
103 | .success(function(result) {
104 | q.resolve(result.notifications);
105 | }).error(function(err) {
106 | q.reject(err);
107 | });
108 | return q.promise;
109 | }
110 | }
111 |
112 | })();
113 |
--------------------------------------------------------------------------------
/www/templates/menu.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
39 |
50 |
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/www/templates/modals/code_selector.html:
--------------------------------------------------------------------------------
1 |
2 | {{ code.name }}
3 |
4 |
--------------------------------------------------------------------------------
/www/templates/modals/login.html:
--------------------------------------------------------------------------------
1 |
2 |
6 |
28 |
29 |
--------------------------------------------------------------------------------
/www/templates/modals/new_topic.html:
--------------------------------------------------------------------------------
1 |
2 |
7 |
26 |
27 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/www/templates/modals/reply.html:
--------------------------------------------------------------------------------
1 |
2 |
7 |
24 |
25 |
--------------------------------------------------------------------------------
/www/templates/notifications.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | 暂无任何通知
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/www/templates/notifications/follow.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ nf.actor.login }} 于
5 | 开始关注你了。
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/www/templates/notifications/mention.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ nf.actor.login }} 在
5 | 在帖子中提及你
6 |
7 | {{ nf.topic.title }}
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/www/templates/notifications/nodechanged.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | 你发布的话题 {{nf.topic.title}} 由于内容原因于
4 | 被管理员移动到了 {{ nf.node.name }} 节点,请注意查看节点说明。
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/www/templates/notifications/topic.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ nf.actor.login }} 于 发布了新帖:
5 |
6 | {{ nf.topic.title }}
7 |
8 |
9 |
--------------------------------------------------------------------------------
/www/templates/notifications/topicreply.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ nf.actor.login }} 于
5 | 在帖子中回复了:
6 |
7 | {{ nf.topic.title }}
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/www/templates/topic.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
![{{ vm.topic.user.login }}]()
10 |
11 | {{ vm.topic.user.login }}
12 |
13 | {{ vm.topic.node_name }}
14 | {{ vm.topic.created_at | date: 'MM月dd日' }}
15 |
16 |
17 |
18 |
19 |
{{ vm.topic.title }}
20 |
21 |
24 |
25 |
26 |
27 |
28 | {{ vm.topic.likes_count }}> 个赞
29 |
30 |
31 |
32 | {{ vm.topic.replies_count }} 条回复
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 | {{ $index + 1 }} 楼已删除
42 |
43 |
44 |
45 |
46 |
![{{ reply.user.login }}]()
47 |
48 | {{ reply.user.login }}
49 |
50 | {{ reply.likes_count }} 个赞
51 | #{{ $index +1 }}
52 | {{ reply.created_at | date: 'MM月dd日' }}
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
--------------------------------------------------------------------------------
/www/templates/topics.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
7 |
9 |
10 |
11 |
45 |
46 |
--------------------------------------------------------------------------------
/www/templates/user/profile.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
7 |
8 |
9 |
![{{ vm.user.login }}]()
10 |
{{ vm.user.level_name }}
13 |
{{ vm.user.name }}
14 |
15 | @{{ vm.user.login }}
16 |
17 |
18 |
19 |
20 |
21 |
24 |
25 |
26 |
29 |
30 |
31 |
32 |
33 |
34 |
35 | {{ vm.user.followers_count }}
36 | 关注者
37 |
38 |
39 | {{ vm.user.following_count }}
40 | 正在关注
41 |
42 |
43 |
44 |
45 |
46 | 第 {{ vm.user.id }} 位会员
47 | / {{ vm.user.location }} / 注册于 {{ vm.user.created_at | date: 'yyyy-MM-dd' }}
48 |
49 |
50 |
51 |
52 |
53 | {{ vm.user.email }}
54 |
55 |
56 |
57 | {{ vm.user.twitter }}
58 |
59 |
60 |
61 | {{ vm.user.website }}
62 |
63 |
64 |
65 |
66 | 发布的话题
67 | {{ vm.user.topics_count }}
68 |
69 |
70 |
71 | 收藏
72 | {{ vm.user.favorites_count }}
73 |
74 |
75 |
76 |
77 |
--------------------------------------------------------------------------------