├── server
├── .meteor
│ ├── .gitignore
│ ├── release
│ ├── platforms
│ ├── .finished-upgraders
│ ├── .id
│ ├── packages
│ └── versions
├── private
│ └── admin.txt
├── public
│ ├── title_icon.png
│ ├── wechat_icon.png
│ ├── discNGOS-qrcode.jpg
│ ├── bootstrap
│ │ ├── fonts
│ │ │ ├── glyphicons-halflings-regular.eot
│ │ │ ├── glyphicons-halflings-regular.ttf
│ │ │ ├── glyphicons-halflings-regular.woff
│ │ │ └── glyphicons-halflings-regular.woff2
│ │ └── css
│ │ │ └── bootstrap-theme.min.css
│ └── bootstrap-datepicker
│ │ ├── locales
│ │ ├── bootstrap-datepicker.kr.min.js
│ │ ├── bootstrap-datepicker.ja.min.js
│ │ ├── bootstrap-datepicker.zh-TW.min.js
│ │ ├── bootstrap-datepicker.zh-CN.min.js
│ │ ├── bootstrap-datepicker.he.min.js
│ │ ├── bootstrap-datepicker.bg.min.js
│ │ ├── bootstrap-datepicker.cy.min.js
│ │ ├── bootstrap-datepicker.ms.min.js
│ │ ├── bootstrap-datepicker.sw.min.js
│ │ ├── bootstrap-datepicker.nb.min.js
│ │ ├── bootstrap-datepicker.sk.min.js
│ │ ├── bootstrap-datepicker.sq.min.js
│ │ ├── bootstrap-datepicker.sl.min.js
│ │ ├── bootstrap-datepicker.th.min.js
│ │ ├── bootstrap-datepicker.da.min.js
│ │ ├── bootstrap-datepicker.eu.min.js
│ │ ├── bootstrap-datepicker.id.min.js
│ │ ├── bootstrap-datepicker.pt.min.js
│ │ ├── bootstrap-datepicker.az.min.js
│ │ ├── bootstrap-datepicker.hr.min.js
│ │ ├── bootstrap-datepicker.kk.min.js
│ │ ├── bootstrap-datepicker.fa.min.js
│ │ ├── bootstrap-datepicker.mk.min.js
│ │ ├── bootstrap-datepicker.pt-BR.min.js
│ │ ├── bootstrap-datepicker.rs.min.js
│ │ ├── bootstrap-datepicker.sr.min.js
│ │ ├── bootstrap-datepicker.ar.min.js
│ │ ├── bootstrap-datepicker.is.min.js
│ │ ├── bootstrap-datepicker.no.min.js
│ │ ├── bootstrap-datepicker.bs.min.js
│ │ ├── bootstrap-datepicker.cs.min.js
│ │ ├── bootstrap-datepicker.fo.min.js
│ │ ├── bootstrap-datepicker.lv.min.js
│ │ ├── bootstrap-datepicker.ro.min.js
│ │ ├── bootstrap-datepicker.tr.min.js
│ │ ├── bootstrap-datepicker.gl.min.js
│ │ ├── bootstrap-datepicker.hu.min.js
│ │ ├── bootstrap-datepicker.pl.min.js
│ │ ├── bootstrap-datepicker.rs-latin.min.js
│ │ ├── bootstrap-datepicker.sr-latin.min.js
│ │ ├── bootstrap-datepicker.sv.min.js
│ │ ├── bootstrap-datepicker.es.min.js
│ │ ├── bootstrap-datepicker.nl.min.js
│ │ ├── bootstrap-datepicker.ca.min.js
│ │ ├── bootstrap-datepicker.de.min.js
│ │ ├── bootstrap-datepicker.fr-CH.min.js
│ │ ├── bootstrap-datepicker.kh.min.js
│ │ ├── bootstrap-datepicker.lt.min.js
│ │ ├── bootstrap-datepicker.me.min.js
│ │ ├── bootstrap-datepicker.en-GB.min.js
│ │ ├── bootstrap-datepicker.ru.min.js
│ │ ├── bootstrap-datepicker.it.min.js
│ │ ├── bootstrap-datepicker.nl-BE.min.js
│ │ ├── bootstrap-datepicker.uk.min.js
│ │ ├── bootstrap-datepicker.vi.min.js
│ │ ├── bootstrap-datepicker.fi.min.js
│ │ ├── bootstrap-datepicker.hy.min.js
│ │ ├── bootstrap-datepicker.it-CH.min.js
│ │ ├── bootstrap-datepicker.fr.min.js
│ │ ├── bootstrap-datepicker.ka.min.js
│ │ ├── bootstrap-datepicker.el.min.js
│ │ └── bootstrap-datepicker.et.min.js
│ │ └── css
│ │ ├── bootstrap-datepicker.min.css
│ │ ├── bootstrap-datepicker.standalone.min.css
│ │ └── bootstrap-datepicker.css
├── client
│ ├── templates
│ │ ├── about.css
│ │ ├── about.js
│ │ ├── chat-record-detail.html
│ │ ├── wechat-live-server.js
│ │ ├── top-activity.html
│ │ ├── user-records.html
│ │ ├── history.js
│ │ ├── top-activity.js
│ │ ├── history.html
│ │ ├── wechat-live-server.html
│ │ ├── chat-record-detail.js
│ │ ├── about.html
│ │ ├── user-records.js
│ │ └── wechat-live-server.css
│ └── head.html
├── lib
│ ├── top-collections.js
│ ├── router.js
│ └── collections.js
└── server
│ └── server.js
├── phone
├── libs
│ ├── Android-DDP.jar
│ └── android-support-v4.jar
├── res
│ ├── drawable-hdpi
│ │ └── icon.png
│ ├── xml
│ │ └── wxlive_accessibility_service_config.xml
│ ├── values-zh-rCN
│ │ └── strings.xml
│ ├── values
│ │ └── strings.xml
│ └── layout
│ │ └── main.xml
├── .gitignore
├── src
│ └── mobi
│ │ └── espier
│ │ └── lgc
│ │ ├── util
│ │ ├── WeakHandlerTemplate.java
│ │ ├── SecurityUtils.java
│ │ ├── LgcUtils.java
│ │ ├── LogUtils.java
│ │ └── PreferencesUtil.java
│ │ ├── data
│ │ ├── LgcDBHelper.java
│ │ ├── LgcDataUtil.java
│ │ ├── UploadHelper.java
│ │ ├── LgcProvider.java
│ │ └── MeteorHelper.java
│ │ ├── service
│ │ └── LgcAccessibilityService.java
│ │ ├── LgcApp.java
│ │ └── LgcActivity.java
└── AndroidManifest.xml
└── README.md
/server/.meteor/.gitignore:
--------------------------------------------------------------------------------
1 | local
2 |
--------------------------------------------------------------------------------
/server/.meteor/release:
--------------------------------------------------------------------------------
1 | METEOR@1.1.0.2
2 |
--------------------------------------------------------------------------------
/server/.meteor/platforms:
--------------------------------------------------------------------------------
1 | server
2 | browser
3 |
--------------------------------------------------------------------------------
/server/private/admin.txt:
--------------------------------------------------------------------------------
1 | {"username":"username","password":"password"}
2 |
--------------------------------------------------------------------------------
/phone/libs/Android-DDP.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/foxsen/live-group-chat/master/phone/libs/Android-DDP.jar
--------------------------------------------------------------------------------
/server/public/title_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/foxsen/live-group-chat/master/server/public/title_icon.png
--------------------------------------------------------------------------------
/server/public/wechat_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/foxsen/live-group-chat/master/server/public/wechat_icon.png
--------------------------------------------------------------------------------
/phone/libs/android-support-v4.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/foxsen/live-group-chat/master/phone/libs/android-support-v4.jar
--------------------------------------------------------------------------------
/phone/res/drawable-hdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/foxsen/live-group-chat/master/phone/res/drawable-hdpi/icon.png
--------------------------------------------------------------------------------
/server/client/templates/about.css:
--------------------------------------------------------------------------------
1 | /* CSS declarations go here */
2 |
3 | .indent_p {
4 | text-indent: 2em;
5 | }
6 |
7 |
--------------------------------------------------------------------------------
/server/public/discNGOS-qrcode.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/foxsen/live-group-chat/master/server/public/discNGOS-qrcode.jpg
--------------------------------------------------------------------------------
/server/public/bootstrap/fonts/glyphicons-halflings-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/foxsen/live-group-chat/master/server/public/bootstrap/fonts/glyphicons-halflings-regular.eot
--------------------------------------------------------------------------------
/server/public/bootstrap/fonts/glyphicons-halflings-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/foxsen/live-group-chat/master/server/public/bootstrap/fonts/glyphicons-halflings-regular.ttf
--------------------------------------------------------------------------------
/server/public/bootstrap/fonts/glyphicons-halflings-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/foxsen/live-group-chat/master/server/public/bootstrap/fonts/glyphicons-halflings-regular.woff
--------------------------------------------------------------------------------
/server/public/bootstrap/fonts/glyphicons-halflings-regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/foxsen/live-group-chat/master/server/public/bootstrap/fonts/glyphicons-halflings-regular.woff2
--------------------------------------------------------------------------------
/phone/.gitignore:
--------------------------------------------------------------------------------
1 | *.class
2 | *.apk
3 | *.ap_
4 | *.swp
5 | tags
6 | bin/
7 | gen/
8 | proguard/
9 | .classpath
10 | .project
11 | tests/
12 | .settings/
13 | format.sh
14 | project.properties
15 | local.properties
16 | *.properties
17 |
--------------------------------------------------------------------------------
/server/.meteor/.finished-upgraders:
--------------------------------------------------------------------------------
1 | # This file contains information which helps Meteor properly upgrade your
2 | # app when you run 'meteor update'. You should check it into version control
3 | # with your project.
4 |
5 | notices-for-0.9.0
6 | notices-for-0.9.1
7 | 0.9.4-platform-file
8 | notices-for-facebook-graph-api-2
9 |
--------------------------------------------------------------------------------
/server/client/templates/about.js:
--------------------------------------------------------------------------------
1 | Template.about.onRendered(function () {
2 | var self = this;
3 | var div = self.find('#list_content_ul');
4 | var iHeight = document.documentElement.clientHeight || document.body.clientHeight;
5 | var header = self.find('#panel_heading');
6 | div.style.height = iHeight - 5 - header.offsetHeight + "px";
7 | });
8 |
--------------------------------------------------------------------------------
/server/.meteor/.id:
--------------------------------------------------------------------------------
1 | # This file contains a token that is unique to your project.
2 | # Check it into your repository along with the rest of this directory.
3 | # It can be used for purposes such as:
4 | # - ensuring you don't accidentally deploy one app on top of another
5 | # - providing package authors with aggregated statistics
6 |
7 | 1fu1e451yg2hsx17ba4ha
8 |
--------------------------------------------------------------------------------
/server/.meteor/packages:
--------------------------------------------------------------------------------
1 | # Meteor packages used by this project, one per line.
2 | # Check this file (and the other files in this directory) into your repository.
3 | #
4 | # 'meteor add' and 'meteor remove' will edit this file for you,
5 | # but you can also edit it by hand.
6 |
7 | meteor-platform
8 | iron:router
9 | jparker:crypto-core
10 | jparker:crypto-md5
11 | accounts-password
12 |
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.kr.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.kr={days:["일요일","월요일","화요일","수요일","목요일","금요일","토요일","일요일"],daysShort:["일","월","화","수","목","금","토","일"],daysMin:["일","월","화","수","목","금","토","일"],months:["1월","2월","3월","4월","5월","6월","7월","8월","9월","10월","11월","12월"],monthsShort:["1월","2월","3월","4월","5월","6월","7월","8월","9월","10월","11월","12월"]}}(jQuery);
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.ja.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.ja={days:["日曜","月曜","火曜","水曜","木曜","金曜","土曜","日曜"],daysShort:["日","月","火","水","木","金","土","日"],daysMin:["日","月","火","水","木","金","土","日"],months:["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],monthsShort:["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],today:"今日",format:"yyyy/mm/dd",clear:"クリア"}}(jQuery);
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.zh-TW.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates["zh-TW"]={days:["星期日","星期一","星期二","星期三","星期四","星期五","星期六","星期日"],daysShort:["週日","週一","週二","週三","週四","週五","週六","週日"],daysMin:["日","一","二","三","四","五","六","日"],months:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],monthsShort:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],today:"今天",format:"yyyy年mm月dd日",weekStart:1}}(jQuery);
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.zh-CN.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates["zh-CN"]={days:["星期日","星期一","星期二","星期三","星期四","星期五","星期六","星期日"],daysShort:["周日","周一","周二","周三","周四","周五","周六","周日"],daysMin:["日","一","二","三","四","五","六","日"],months:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],monthsShort:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],today:"今日",format:"yyyy年mm月dd日",weekStart:1,clear:"清空"}}(jQuery);
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.he.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.he={days:["ראשון","שני","שלישי","רביעי","חמישי","שישי","שבת","ראשון"],daysShort:["א","ב","ג","ד","ה","ו","ש","א"],daysMin:["א","ב","ג","ד","ה","ו","ש","א"],months:["ינואר","פברואר","מרץ","אפריל","מאי","יוני","יולי","אוגוסט","ספטמבר","אוקטובר","נובמבר","דצמבר"],monthsShort:["ינו","פבר","מרץ","אפר","מאי","יונ","יול","אוג","ספט","אוק","נוב","דצמ"],today:"היום",rtl:!0}}(jQuery);
--------------------------------------------------------------------------------
/server/client/templates/chat-record-detail.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{nickId}}
6 |
7 |
8 | {{createdAtHuman createdAt}}
9 |
10 |
11 |
12 |
13 | {{content}}
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.bg.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.bg={days:["Неделя","Понеделник","Вторник","Сряда","Четвъртък","Петък","Събота","Неделя"],daysShort:["Нед","Пон","Вто","Сря","Чет","Пет","Съб","Нед"],daysMin:["Н","П","В","С","Ч","П","С","Н"],months:["Януари","Февруари","Март","Април","Май","Юни","Юли","Август","Септември","Октомври","Ноември","Декември"],monthsShort:["Ян","Фев","Мар","Апр","Май","Юни","Юли","Авг","Сеп","Окт","Ное","Дек"],today:"днес"}}(jQuery);
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.cy.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.cy={days:["Sul","Llun","Mawrth","Mercher","Iau","Gwener","Sadwrn","Sul"],daysShort:["Sul","Llu","Maw","Mer","Iau","Gwe","Sad","Sul"],daysMin:["Su","Ll","Ma","Me","Ia","Gwe","Sa","Su"],months:["Ionawr","Chewfror","Mawrth","Ebrill","Mai","Mehefin","Gorfennaf","Awst","Medi","Hydref","Tachwedd","Rhagfyr"],monthsShort:["Ion","Chw","Maw","Ebr","Mai","Meh","Gor","Aws","Med","Hyd","Tach","Rha"],today:"Heddiw"}}(jQuery);
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.ms.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.ms={days:["Ahad","Isnin","Selasa","Rabu","Khamis","Jumaat","Sabtu","Ahad"],daysShort:["Aha","Isn","Sel","Rab","Kha","Jum","Sab","Aha"],daysMin:["Ah","Is","Se","Ra","Kh","Ju","Sa","Ah"],months:["Januari","Februari","Mac","April","Mei","Jun","Julai","Ogos","September","Oktober","November","Disember"],monthsShort:["Jan","Feb","Mar","Apr","Mei","Jun","Jul","Ogo","Sep","Okt","Nov","Dis"],today:"Hari Ini"}}(jQuery);
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.sw.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.sw={days:["Jumapili","Jumatatu","Jumanne","Jumatano","Alhamisi","Ijumaa","Jumamosi","Jumapili"],daysShort:["J2","J3","J4","J5","Alh","Ij","J1","J2"],daysMin:["2","3","4","5","A","I","1","2"],months:["Januari","Februari","Machi","Aprili","Mei","Juni","Julai","Agosti","Septemba","Oktoba","Novemba","Desemba"],monthsShort:["Jan","Feb","Mac","Apr","Mei","Jun","Jul","Ago","Sep","Okt","Nov","Des"],today:"Leo"}}(jQuery);
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.nb.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.nb={days:["Søndag","Mandag","Tirsdag","Onsdag","Torsdag","Fredag","Lørdag","Søndag"],daysShort:["Søn","Man","Tir","Ons","Tor","Fre","Lør","Søn"],daysMin:["Sø","Ma","Ti","On","To","Fr","Lø","Sø"],months:["Januar","Februar","Mars","April","Mai","Juni","Juli","August","September","Oktober","November","Desember"],monthsShort:["Jan","Feb","Mar","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Des"],today:"I Dag"}}(jQuery);
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.sk.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.sk={days:["Nedeľa","Pondelok","Utorok","Streda","Štvrtok","Piatok","Sobota","Nedeľa"],daysShort:["Ned","Pon","Uto","Str","Štv","Pia","Sob","Ned"],daysMin:["Ne","Po","Ut","St","Št","Pia","So","Ne"],months:["Január","Február","Marec","Apríl","Máj","Jún","Júl","August","September","Október","November","December"],monthsShort:["Jan","Feb","Mar","Apr","Máj","Jún","Júl","Aug","Sep","Okt","Nov","Dec"],today:"Dnes"}}(jQuery);
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.sq.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.sq={days:["E Diel","E Hënë","E Martē","E Mërkurë","E Enjte","E Premte","E Shtunë","E Diel"],daysShort:["Die","Hën","Mar","Mër","Enj","Pre","Shtu","Die"],daysMin:["Di","Hë","Ma","Më","En","Pr","Sht","Di"],months:["Janar","Shkurt","Mars","Prill","Maj","Qershor","Korrik","Gusht","Shtator","Tetor","Nëntor","Dhjetor"],monthsShort:["Jan","Shk","Mar","Pri","Maj","Qer","Korr","Gu","Sht","Tet","Nën","Dhjet"],today:"Sot"}}(jQuery);
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.sl.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.sl={days:["Nedelja","Ponedeljek","Torek","Sreda","Četrtek","Petek","Sobota","Nedelja"],daysShort:["Ned","Pon","Tor","Sre","Čet","Pet","Sob","Ned"],daysMin:["Ne","Po","To","Sr","Če","Pe","So","Ne"],months:["Januar","Februar","Marec","April","Maj","Junij","Julij","Avgust","September","Oktober","November","December"],monthsShort:["Jan","Feb","Mar","Apr","Maj","Jun","Jul","Avg","Sep","Okt","Nov","Dec"],today:"Danes"}}(jQuery);
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.th.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.th={days:["อาทิตย์","จันทร์","อังคาร","พุธ","พฤหัส","ศุกร์","เสาร์","อาทิตย์"],daysShort:["อา","จ","อ","พ","พฤ","ศ","ส","อา"],daysMin:["อา","จ","อ","พ","พฤ","ศ","ส","อา"],months:["มกราคม","กุมภาพันธ์","มีนาคม","เมษายน","พฤษภาคม","มิถุนายน","กรกฎาคม","สิงหาคม","กันยายน","ตุลาคม","พฤศจิกายน","ธันวาคม"],monthsShort:["ม.ค.","ก.พ.","มี.ค.","เม.ย.","พ.ค.","มิ.ย.","ก.ค.","ส.ค.","ก.ย.","ต.ค.","พ.ย.","ธ.ค."],today:"วันนี้"}}(jQuery);
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.da.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.da={days:["Søndag","Mandag","Tirsdag","Onsdag","Torsdag","Fredag","Lørdag","Søndag"],daysShort:["Søn","Man","Tir","Ons","Tor","Fre","Lør","Søn"],daysMin:["Sø","Ma","Ti","On","To","Fr","Lø","Sø"],months:["Januar","Februar","Marts","April","Maj","Juni","Juli","August","September","Oktober","November","December"],monthsShort:["Jan","Feb","Mar","Apr","Maj","Jun","Jul","Aug","Sep","Okt","Nov","Dec"],today:"I Dag",clear:"Nulstil"}}(jQuery);
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.eu.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.eu={days:["Igandea","Astelehena","Asteartea","Asteazkena","Osteguna","Ostirala","Larunbata","Igandea"],daysShort:["Ig","Al","Ar","Az","Og","Ol","Lr","Ig"],daysMin:["Ig","Al","Ar","Az","Og","Ol","Lr","Ig"],months:["Urtarrila","Otsaila","Martxoa","Apirila","Maiatza","Ekaina","Uztaila","Abuztua","Iraila","Urria","Azaroa","Abendua"],monthsShort:["Urt","Ots","Mar","Api","Mai","Eka","Uzt","Abu","Ira","Urr","Aza","Abe"],today:"Gaur"}}(jQuery);
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.id.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.id={days:["Minggu","Senin","Selasa","Rabu","Kamis","Jumat","Sabtu","Minggu"],daysShort:["Mgu","Sen","Sel","Rab","Kam","Jum","Sab","Mgu"],daysMin:["Mg","Sn","Sl","Ra","Ka","Ju","Sa","Mg"],months:["Januari","Februari","Maret","April","Mei","Juni","Juli","Agustus","September","Oktober","November","Desember"],monthsShort:["Jan","Feb","Mar","Apr","Mei","Jun","Jul","Ags","Sep","Okt","Nov","Des"],today:"Hari Ini",clear:"Kosongkan"}}(jQuery);
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.pt.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.pt={days:["Domingo","Segunda","Terça","Quarta","Quinta","Sexta","Sábado","Domingo"],daysShort:["Dom","Seg","Ter","Qua","Qui","Sex","Sáb","Dom"],daysMin:["Do","Se","Te","Qu","Qu","Se","Sa","Do"],months:["Janeiro","Fevereiro","Março","Abril","Maio","Junho","Julho","Agosto","Setembro","Outubro","Novembro","Dezembro"],monthsShort:["Jan","Fev","Mar","Abr","Mai","Jun","Jul","Ago","Set","Out","Nov","Dez"],today:"Hoje",clear:"Limpar"}}(jQuery);
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.az.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.az={days:["Bazar","Bazar ertəsi","Çərşənbə axşamı","Çərşənbə","Cümə axşamı","Cümə","Şənbə","Bazar"],daysShort:["B.","B.e","Ç.a","Ç.","C.a","C.","Ş.","B."],daysMin:["B.","B.e","Ç.a","Ç.","C.a","C.","Ş.","B."],months:["Yanvar","Fevral","Mart","Aprel","May","İyun","İyul","Avqust","Sentyabr","Oktyabr","Noyabr","Dekabr"],monthsShort:["Yan","Fev","Mar","Apr","May","İyun","İyul","Avq","Sen","Okt","Noy","Dek"],today:"Bu gün",weekStart:1}}(jQuery);
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.hr.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.hr={days:["Nedjelja","Ponedjeljak","Utorak","Srijeda","Četvrtak","Petak","Subota","Nedjelja"],daysShort:["Ned","Pon","Uto","Sri","Čet","Pet","Sub","Ned"],daysMin:["Ne","Po","Ut","Sr","Če","Pe","Su","Ne"],months:["Siječanj","Veljača","Ožujak","Travanj","Svibanj","Lipanj","Srpanj","Kolovoz","Rujan","Listopad","Studeni","Prosinac"],monthsShort:["Sij","Velj","Ožu","Tra","Svi","Lip","Srp","Kol","Ruj","Lis","Stu","Pro"],today:"Danas"}}(jQuery);
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.kk.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.kk={days:["Жексенбі","Дүйсенбі","Сейсенбі","Сәрсенбі","Бейсенбі","Жұма","Сенбі","Жексенбі"],daysShort:["Жек","Дүй","Сей","Сәр","Бей","Жұм","Сен","Жек"],daysMin:["Жк","Дс","Сс","Ср","Бс","Жм","Сн","Жк"],months:["Қаңтар","Ақпан","Наурыз","Сәуір","Мамыр","Маусым","Шілде","Тамыз","Қыркүйек","Қазан","Қараша","Желтоқсан"],monthsShort:["Қаң","Ақп","Нау","Сәу","Мамыр","Мау","Шлд","Тмз","Қыр","Қзн","Қар","Жел"],today:"Бүгін",weekStart:1}}(jQuery);
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.fa.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.fa={days:["یکشنبه","دوشنبه","سهشنبه","چهارشنبه","پنجشنبه","جمعه","شنبه","یکشنبه"],daysShort:["یک","دو","سه","چهار","پنج","جمعه","شنبه","یک"],daysMin:["ی","د","س","چ","پ","ج","ش","ی"],months:["ژانویه","فوریه","مارس","آوریل","مه","ژوئن","ژوئیه","اوت","سپتامبر","اکتبر","نوامبر","دسامبر"],monthsShort:["ژان","فور","مار","آور","مه","ژون","ژوی","اوت","سپت","اکت","نوا","دسا"],today:"امروز",clear:"پاک کن",weekStart:1,format:"yyyy/mm/dd"}}(jQuery);
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.mk.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.mk={days:["Недела","Понеделник","Вторник","Среда","Четврток","Петок","Сабота","Недела"],daysShort:["Нед","Пон","Вто","Сре","Чет","Пет","Саб","Нед"],daysMin:["Не","По","Вт","Ср","Че","Пе","Са","Не"],months:["Јануари","Февруари","Март","Април","Мај","Јуни","Јули","Август","Септември","Октомври","Ноември","Декември"],monthsShort:["Јан","Фев","Мар","Апр","Мај","Јун","Јул","Авг","Сеп","Окт","Ное","Дек"],today:"Денес",format:"dd.mm.yyyy"}}(jQuery);
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.pt-BR.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates["pt-BR"]={days:["Domingo","Segunda","Terça","Quarta","Quinta","Sexta","Sábado","Domingo"],daysShort:["Dom","Seg","Ter","Qua","Qui","Sex","Sáb","Dom"],daysMin:["Do","Se","Te","Qu","Qu","Se","Sa","Do"],months:["Janeiro","Fevereiro","Março","Abril","Maio","Junho","Julho","Agosto","Setembro","Outubro","Novembro","Dezembro"],monthsShort:["Jan","Fev","Mar","Abr","Mai","Jun","Jul","Ago","Set","Out","Nov","Dez"],today:"Hoje",clear:"Limpar"}}(jQuery);
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.rs.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.rs={days:["Недеља","Понедељак","Уторак","Среда","Четвртак","Петак","Субота","Недеља"],daysShort:["Нед","Пон","Уто","Сре","Чет","Пет","Суб","Нед"],daysMin:["Н","По","У","Ср","Ч","Пе","Су","Н"],months:["Јануар","Фебруар","Март","Април","Мај","Јун","Јул","Август","Септембар","Октобар","Новембар","Децембар"],monthsShort:["Јан","Феб","Мар","Апр","Мај","Јун","Јул","Авг","Сеп","Окт","Нов","Дец"],today:"Данас",weekStart:1,format:"dd.mm.yyyy"}}(jQuery);
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.sr.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.sr={days:["Недеља","Понедељак","Уторак","Среда","Четвртак","Петак","Субота","Недеља"],daysShort:["Нед","Пон","Уто","Сре","Чет","Пет","Суб","Нед"],daysMin:["Н","По","У","Ср","Ч","Пе","Су","Н"],months:["Јануар","Фебруар","Март","Април","Мај","Јун","Јул","Август","Септембар","Октобар","Новембар","Децембар"],monthsShort:["Јан","Феб","Мар","Апр","Мај","Јун","Јул","Авг","Сеп","Окт","Нов","Дец"],today:"Данас",weekStart:1,format:"dd.mm.yyyy"}}(jQuery);
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.ar.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.ar={days:["الأحد","الاثنين","الثلاثاء","الأربعاء","الخميس","الجمعة","السبت","الأحد"],daysShort:["أحد","اثنين","ثلاثاء","أربعاء","خميس","جمعة","سبت","أحد"],daysMin:["ح","ن","ث","ع","خ","ج","س","ح"],months:["يناير","فبراير","مارس","أبريل","مايو","يونيو","يوليو","أغسطس","سبتمبر","أكتوبر","نوفمبر","ديسمبر"],monthsShort:["يناير","فبراير","مارس","أبريل","مايو","يونيو","يوليو","أغسطس","سبتمبر","أكتوبر","نوفمبر","ديسمبر"],today:"هذا اليوم",rtl:!0}}(jQuery);
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.is.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.is={days:["Sunnudagur","Mánudagur","Þriðjudagur","Miðvikudagur","Fimmtudagur","Föstudagur","Laugardagur","Sunnudagur"],daysShort:["Sun","Mán","Þri","Mið","Fim","Fös","Lau","Sun"],daysMin:["Su","Má","Þr","Mi","Fi","Fö","La","Su"],months:["Janúar","Febrúar","Mars","Apríl","Maí","Júní","Júlí","Ágúst","September","Október","Nóvember","Desember"],monthsShort:["Jan","Feb","Mar","Apr","Maí","Jún","Júl","Ágú","Sep","Okt","Nóv","Des"],today:"Í Dag"}}(jQuery);
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.no.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.no={days:["Søndag","Mandag","Tirsdag","Onsdag","Torsdag","Fredag","Lørdag"],daysShort:["Søn","Man","Tir","Ons","Tor","Fre","Lør"],daysMin:["Sø","Ma","Ti","On","To","Fr","Lø"],months:["Januar","Februar","Mars","April","Mai","Juni","Juli","August","September","Oktober","November","Desember"],monthsShort:["Jan","Feb","Mar","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Des"],today:"I dag",clear:"Nullstill",weekStart:1,format:"dd.mm.yyyy"}}(jQuery);
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.bs.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.bs={days:["Nedjelja","Ponedjeljak","Utorak","Srijeda","Četvrtak","Petak","Subota","Nedjelja"],daysShort:["Ned","Pon","Uto","Sri","Čet","Pet","Sub","Ned"],daysMin:["N","Po","U","Sr","Č","Pe","Su","N"],months:["Januar","Februar","Mart","April","Maj","Juni","Juli","August","Septembar","Oktobar","Novembar","Decembar"],monthsShort:["Jan","Feb","Mar","Apr","Maj","Jun","Jul","Aug","Sep","Okt","Nov","Dec"],today:"Danas",weekStart:1,format:"dd.mm.yyyy"}}(jQuery);
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.cs.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.cs={days:["Neděle","Pondělí","Úterý","Středa","Čtvrtek","Pátek","Sobota","Neděle"],daysShort:["Ned","Pon","Úte","Stř","Čtv","Pát","Sob","Ned"],daysMin:["Ne","Po","Út","St","Čt","Pá","So","Ne"],months:["Leden","Únor","Březen","Duben","Květen","Červen","Červenec","Srpen","Září","Říjen","Listopad","Prosinec"],monthsShort:["Led","Úno","Bře","Dub","Kvě","Čer","Čnc","Srp","Zář","Říj","Lis","Pro"],today:"Dnes",clear:"Vymazat",weekStart:1,format:"d.m.yyyy"}}(jQuery);
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.fo.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.fo={days:["Sunnudagur","Mánadagur","Týsdagur","Mikudagur","Hósdagur","Fríggjadagur","Leygardagur","Sunnudagur"],daysShort:["Sun","Mán","Týs","Mik","Hós","Frí","Ley","Sun"],daysMin:["Su","Má","Tý","Mi","Hó","Fr","Le","Su"],months:["Januar","Februar","Marts","Apríl","Mei","Juni","Juli","August","Septembur","Oktobur","Novembur","Desembur"],monthsShort:["Jan","Feb","Mar","Apr","Mei","Jun","Jul","Aug","Sep","Okt","Nov","Des"],today:"Í Dag",clear:"Reinsa"}}(jQuery);
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.lv.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.lv={days:["Svētdiena","Pirmdiena","Otrdiena","Trešdiena","Ceturtdiena","Piektdiena","Sestdiena","Svētdiena"],daysShort:["Sv","P","O","T","C","Pk","S","Sv"],daysMin:["Sv","Pr","Ot","Tr","Ce","Pk","Se","Sv"],months:["Janvāris","Februāris","Marts","Aprīlis","Maijs","Jūnijs","Jūlijs","Augusts","Septembris","Oktobris","Novembris","Decembris"],monthsShort:["Jan","Feb","Mar","Apr","Mai","Jūn","Jūl","Aug","Sep","Okt","Nov","Dec"],today:"Šodien",weekStart:1}}(jQuery);
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.ro.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.ro={days:["Duminică","Luni","Marţi","Miercuri","Joi","Vineri","Sâmbătă","Duminică"],daysShort:["Dum","Lun","Mar","Mie","Joi","Vin","Sâm","Dum"],daysMin:["Du","Lu","Ma","Mi","Jo","Vi","Sâ","Du"],months:["Ianuarie","Februarie","Martie","Aprilie","Mai","Iunie","Iulie","August","Septembrie","Octombrie","Noiembrie","Decembrie"],monthsShort:["Ian","Feb","Mar","Apr","Mai","Iun","Iul","Aug","Sep","Oct","Nov","Dec"],today:"Astăzi",clear:"Șterge",weekStart:1}}(jQuery);
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.tr.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.tr={days:["Pazar","Pazartesi","Salı","Çarşamba","Perşembe","Cuma","Cumartesi","Pazar"],daysShort:["Pz","Pzt","Sal","Çrş","Prş","Cu","Cts","Pz"],daysMin:["Pz","Pzt","Sa","Çr","Pr","Cu","Ct","Pz"],months:["Ocak","Şubat","Mart","Nisan","Mayıs","Haziran","Temmuz","Ağustos","Eylül","Ekim","Kasım","Aralık"],monthsShort:["Oca","Şub","Mar","Nis","May","Haz","Tem","Ağu","Eyl","Eki","Kas","Ara"],today:"Bugün",clear:"Temizle",weekStart:1,format:"dd.mm.yyyy"}}(jQuery);
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.gl.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.gl={days:["Domingo","Luns","Martes","Mércores","Xoves","Venres","Sábado","Domingo"],daysShort:["Dom","Lun","Mar","Mér","Xov","Ven","Sáb","Dom"],daysMin:["Do","Lu","Ma","Me","Xo","Ve","Sa","Do"],months:["Xaneiro","Febreiro","Marzo","Abril","Maio","Xuño","Xullo","Agosto","Setembro","Outubro","Novembro","Decembro"],monthsShort:["Xan","Feb","Mar","Abr","Mai","Xun","Xul","Ago","Sep","Out","Nov","Dec"],today:"Hoxe",clear:"Limpar",weekStart:1,format:"dd/mm/yyyy"}}(jQuery);
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.hu.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.hu={days:["Vasárnap","Hétfő","Kedd","Szerda","Csütörtök","Péntek","Szombat","Vasárnap"],daysShort:["Vas","Hét","Ked","Sze","Csü","Pén","Szo","Vas"],daysMin:["Va","Hé","Ke","Sz","Cs","Pé","Sz","Va"],months:["Január","Február","Március","Április","Május","Június","Július","Augusztus","Szeptember","Október","November","December"],monthsShort:["Jan","Feb","Már","Ápr","Máj","Jún","Júl","Aug","Sze","Okt","Nov","Dec"],today:"Ma",weekStart:1,format:"yyyy.mm.dd"}}(jQuery);
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.pl.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.pl={days:["Niedziela","Poniedziałek","Wtorek","Środa","Czwartek","Piątek","Sobota","Niedziela"],daysShort:["Nie","Pn","Wt","Śr","Czw","Pt","So","Nie"],daysMin:["N","Pn","Wt","Śr","Cz","Pt","So","N"],months:["Styczeń","Luty","Marzec","Kwiecień","Maj","Czerwiec","Lipiec","Sierpień","Wrzesień","Październik","Listopad","Grudzień"],monthsShort:["Sty","Lu","Mar","Kw","Maj","Cze","Lip","Sie","Wrz","Pa","Lis","Gru"],today:"Dzisiaj",weekStart:1,clear:"Wyczyść"}}(jQuery);
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.rs-latin.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates["rs-latin"]={days:["Nedelja","Ponedeljak","Utorak","Sreda","Četvrtak","Petak","Subota","Nedelja"],daysShort:["Ned","Pon","Uto","Sre","Čet","Pet","Sub","Ned"],daysMin:["N","Po","U","Sr","Č","Pe","Su","N"],months:["Januar","Februar","Mart","April","Maj","Jun","Jul","Avgust","Septembar","Oktobar","Novembar","Decembar"],monthsShort:["Jan","Feb","Mar","Apr","Maj","Jun","Jul","Avg","Sep","Okt","Nov","Dec"],today:"Danas",weekStart:1,format:"dd.mm.yyyy"}}(jQuery);
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.sr-latin.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates["sr-latin"]={days:["Nedelja","Ponedeljak","Utorak","Sreda","Četvrtak","Petak","Subota","Nedelja"],daysShort:["Ned","Pon","Uto","Sre","Čet","Pet","Sub","Ned"],daysMin:["N","Po","U","Sr","Č","Pe","Su","N"],months:["Januar","Februar","Mart","April","Maj","Jun","Jul","Avgust","Septembar","Oktobar","Novembar","Decembar"],monthsShort:["Jan","Feb","Mar","Apr","Maj","Jun","Jul","Avg","Sep","Okt","Nov","Dec"],today:"Danas",weekStart:1,format:"dd.mm.yyyy"}}(jQuery);
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.sv.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.sv={days:["Söndag","Måndag","Tisdag","Onsdag","Torsdag","Fredag","Lördag","Söndag"],daysShort:["Sön","Mån","Tis","Ons","Tor","Fre","Lör","Sön"],daysMin:["Sö","Må","Ti","On","To","Fr","Lö","Sö"],months:["Januari","Februari","Mars","April","Maj","Juni","Juli","Augusti","September","Oktober","November","December"],monthsShort:["Jan","Feb","Mar","Apr","Maj","Jun","Jul","Aug","Sep","Okt","Nov","Dec"],today:"Idag",format:"yyyy-mm-dd",weekStart:1,clear:"Rensa"}}(jQuery);
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.es.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.es={days:["Domingo","Lunes","Martes","Miércoles","Jueves","Viernes","Sábado","Domingo"],daysShort:["Dom","Lun","Mar","Mié","Jue","Vie","Sáb","Dom"],daysMin:["Do","Lu","Ma","Mi","Ju","Vi","Sa","Do"],months:["Enero","Febrero","Marzo","Abril","Mayo","Junio","Julio","Agosto","Septiembre","Octubre","Noviembre","Diciembre"],monthsShort:["Ene","Feb","Mar","Abr","May","Jun","Jul","Ago","Sep","Oct","Nov","Dic"],today:"Hoy",clear:"Borrar",weekStart:1,format:"dd/mm/yyyy"}}(jQuery);
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.nl.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.nl={days:["zondag","maandag","dinsdag","woensdag","donderdag","vrijdag","zaterdag","zondag"],daysShort:["zo","ma","di","wo","do","vr","za","zo"],daysMin:["zo","ma","di","wo","do","vr","za","zo"],months:["januari","februari","maart","april","mei","juni","juli","augustus","september","oktober","november","december"],monthsShort:["jan","feb","mrt","apr","mei","jun","jul","aug","sep","okt","nov","dec"],today:"Vandaag",clear:"Wissen",weekStart:1,format:"dd-mm-yyyy"}}(jQuery);
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.ca.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.ca={days:["Diumenge","Dilluns","Dimarts","Dimecres","Dijous","Divendres","Dissabte","Diumenge"],daysShort:["Diu","Dil","Dmt","Dmc","Dij","Div","Dis","Diu"],daysMin:["dg","dl","dt","dc","dj","dv","ds","dg"],months:["Gener","Febrer","Març","Abril","Maig","Juny","Juliol","Agost","Setembre","Octubre","Novembre","Desembre"],monthsShort:["Gen","Feb","Mar","Abr","Mai","Jun","Jul","Ago","Set","Oct","Nov","Des"],today:"Avui",clear:"Esborrar",weekStart:1,format:"dd/mm/yyyy"}}(jQuery);
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.de.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.de={days:["Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag","Sonntag"],daysShort:["Son","Mon","Die","Mit","Don","Fre","Sam","Son"],daysMin:["So","Mo","Di","Mi","Do","Fr","Sa","So"],months:["Januar","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember"],monthsShort:["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],today:"Heute",clear:"Löschen",weekStart:1,format:"dd.mm.yyyy"}}(jQuery);
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.fr-CH.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.fr={days:["Dimanche","Lundi","Mardi","Mercredi","Jeudi","Vendredi","Samedi","Dimanche"],daysShort:["Dim","Lun","Mar","Mer","Jeu","Ven","Sam","Dim"],daysMin:["D","L","Ma","Me","J","V","S","D"],months:["Janvier","Février","Mars","Avril","Mai","Juin","Juillet","Août","Septembre","Octobre","Novembre","Décembre"],monthsShort:["Jan","Fév","Mar","Avr","Mai","Jui","Jul","Aou","Sep","Oct","Nov","Déc"],today:"Aujourd'hui",clear:"Effacer",weekStart:1,format:"dd.mm.yyyy"}}(jQuery);
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.kh.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.kh={days:["អាទិត្យ","ចន្ទ","អង្គារ","ពុធ","ព្រហស្បតិ៍","សុក្រ","សៅរ៍","អាទិត្យ"],daysShort:["អា.ទិ","ចន្ទ","អង្គារ","ពុធ","ព្រ.ហ","សុក្រ","សៅរ៍","អា.ទិ"],daysMin:["អា.ទិ","ចន្ទ","អង្គារ","ពុធ","ព្រ.ហ","សុក្រ","សៅរ៍","អា.ទិ"],months:["មករា","កុម្ភះ","មិនា","មេសា","ឧសភា","មិថុនា","កក្កដា","សីហា","កញ្ញា","តុលា","វិច្ឆិកា","ធ្នូ"],monthsShort:["មករា","កុម្ភះ","មិនា","មេសា","ឧសភា","មិថុនា","កក្កដា","សីហា","កញ្ញា","តុលា","វិច្ឆិកា","ធ្នូ"],today:"ថ្ងៃនេះ",clear:"សំអាត"}}(jQuery);
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.lt.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.lt={days:["Sekmadienis","Pirmadienis","Antradienis","Trečiadienis","Ketvirtadienis","Penktadienis","Šeštadienis","Sekmadienis"],daysShort:["S","Pr","A","T","K","Pn","Š","S"],daysMin:["Sk","Pr","An","Tr","Ke","Pn","Št","Sk"],months:["Sausis","Vasaris","Kovas","Balandis","Gegužė","Birželis","Liepa","Rugpjūtis","Rugsėjis","Spalis","Lapkritis","Gruodis"],monthsShort:["Sau","Vas","Kov","Bal","Geg","Bir","Lie","Rugp","Rugs","Spa","Lap","Gru"],today:"Šiandien",weekStart:1}}(jQuery);
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.me.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.me={days:["Nedjelja","Ponedjeljak","Utorak","Srijeda","Četvrtak","Petak","Subota","Nedjelja"],daysShort:["Ned","Pon","Uto","Sri","Čet","Pet","Sub","Ned"],daysMin:["Ne","Po","Ut","Sr","Če","Pe","Su","Ne"],months:["Januar","Februar","Mart","April","Maj","Jun","Jul","Avgust","Septembar","Oktobar","Novembar","Decembar"],monthsShort:["Jan","Feb","Mar","Apr","Maj","Jun","Jul","Avg","Sep","Okt","Nov","Dec"],today:"Danas",weekStart:1,clear:"Izbriši",format:"dd.mm.yyyy"}}(jQuery);
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.en-GB.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates["en-GB"]={days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"],daysShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat","Sun"],daysMin:["Su","Mo","Tu","We","Th","Fr","Sa","Su"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],monthsShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],today:"Today",clear:"Clear",weekStart:1,format:"dd/mm/yyyy"}}(jQuery);
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.ru.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.ru={days:["Воскресенье","Понедельник","Вторник","Среда","Четверг","Пятница","Суббота","Воскресенье"],daysShort:["Вск","Пнд","Втр","Срд","Чтв","Птн","Суб","Вск"],daysMin:["Вс","Пн","Вт","Ср","Чт","Пт","Сб","Вс"],months:["Январь","Февраль","Март","Апрель","Май","Июнь","Июль","Август","Сентябрь","Октябрь","Ноябрь","Декабрь"],monthsShort:["Янв","Фев","Мар","Апр","Май","Июн","Июл","Авг","Сен","Окт","Ноя","Дек"],today:"Сегодня",clear:"Очистить",format:"dd.mm.yyyy",weekStart:1}}(jQuery);
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.it.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.it={days:["Domenica","Lunedì","Martedì","Mercoledì","Giovedì","Venerdì","Sabato","Domenica"],daysShort:["Dom","Lun","Mar","Mer","Gio","Ven","Sab","Dom"],daysMin:["Do","Lu","Ma","Me","Gi","Ve","Sa","Do"],months:["Gennaio","Febbraio","Marzo","Aprile","Maggio","Giugno","Luglio","Agosto","Settembre","Ottobre","Novembre","Dicembre"],monthsShort:["Gen","Feb","Mar","Apr","Mag","Giu","Lug","Ago","Set","Ott","Nov","Dic"],today:"Oggi",clear:"Cancella",weekStart:1,format:"dd/mm/yyyy"}}(jQuery);
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.nl-BE.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates["nl-BE"]={days:["zondag","maandag","dinsdag","woensdag","donderdag","vrijdag","zaterdag","zondag"],daysShort:["zo","ma","di","wo","do","vr","za","zo"],daysMin:["zo","ma","di","wo","do","vr","za","zo"],months:["januari","februari","maart","april","mei","juni","juli","augustus","september","oktober","november","december"],monthsShort:["jan","feb","mrt","apr","mei","jun","jul","aug","sep","okt","nov","dec"],today:"Vandaag",clear:"Leegmaken",weekStart:1,format:"dd/mm/yyyy"}}(jQuery);
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.uk.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.uk={days:["Неділя","Понеділок","Вівторок","Середа","Четвер","П'ятниця","Субота","Неділя"],daysShort:["Нед","Пнд","Втр","Срд","Чтв","Птн","Суб","Нед"],daysMin:["Нд","Пн","Вт","Ср","Чт","Пт","Сб","Нд"],months:["Cічень","Лютий","Березень","Квітень","Травень","Червень","Липень","Серпень","Вересень","Жовтень","Листопад","Грудень"],monthsShort:["Січ","Лют","Бер","Кві","Тра","Чер","Лип","Сер","Вер","Жов","Лис","Гру"],today:"Сьогодні",clear:"Очистити",format:"dd.mm.yyyy",weekStart:1}}(jQuery);
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.vi.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.vi={days:["Chủ nhật","Thứ hai","Thứ ba","Thứ tư","Thứ năm","Thứ sáu","Thứ bảy","Chủ nhật"],daysShort:["CN","Thứ 2","Thứ 3","Thứ 4","Thứ 5","Thứ 6","Thứ 7","CN"],daysMin:["CN","T2","T3","T4","T5","T6","T7","CN"],months:["Tháng 1","Tháng 2","Tháng 3","Tháng 4","Tháng 5","Tháng 6","Tháng 7","Tháng 8","Tháng 9","Tháng 10","Tháng 11","Tháng 12"],monthsShort:["Th1","Th2","Th3","Th4","Th5","Th6","Th7","Th8","Th9","Th10","Th11","Th12"],today:"Hôm nay",clear:"Xóa",format:"dd/mm/yyyy"}}(jQuery);
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.fi.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.fi={days:["sunnuntai","maanantai","tiistai","keskiviikko","torstai","perjantai","lauantai","sunnuntai"],daysShort:["sun","maa","tii","kes","tor","per","lau","sun"],daysMin:["su","ma","ti","ke","to","pe","la","su"],months:["tammikuu","helmikuu","maaliskuu","huhtikuu","toukokuu","kesäkuu","heinäkuu","elokuu","syyskuu","lokakuu","marraskuu","joulukuu"],monthsShort:["tam","hel","maa","huh","tou","kes","hei","elo","syy","lok","mar","jou"],today:"tänään",weekStart:1,format:"d.m.yyyy"}}(jQuery);
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.hy.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.hy={days:["Կիրակի","Երկուշաբթի","Երեքշաբթի","Չորեքշաբթի","Հինգշաբթի","Ուրբաթ","Շաբաթ","Կիրակի"],daysShort:["Կիր","Երկ","Երք","Չոր","Հնգ","Ուր","Շաբ","Կիր"],daysMin:["Կի","Եկ","Եք","Չո","Հի","Ու","Շա","Կի"],months:["Հունվար","Փետրվար","Մարտ","Ապրիլ","Մայիս","Հունիս","Հուլիս","Օգոստոս","Սեպտեմբեր","Հոկտեմբեր","Նոյեմբեր","Դեկտեմբեր"],monthsShort:["Հնվ","Փետ","Մար","Ապր","Մայ","Հուն","Հուլ","Օգս","Սեպ","Հոկ","Նոյ","Դեկ"],today:"Այսօր",clear:"Ջնջել",format:"dd.mm.yyyy",weekStart:1}}(jQuery);
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.it-CH.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.it={days:["Domenica","Lunedì","Martedì","Mercoledì","Giovedì","Venerdì","Sabato","Domenica"],daysShort:["Dom","Lun","Mar","Mer","Gio","Ven","Sab","Dom"],daysMin:["Do","Lu","Ma","Me","Gi","Ve","Sa","Do"],months:["Gennaio","Febbraio","Marzo","Aprile","Maggio","Giugno","Luglio","Agosto","Settembre","Ottobre","Novembre","Dicembre"],monthsShort:["Gen","Feb","Mar","Apr","Mag","Giu","Lug","Ago","Set","Ott","Nov","Dic"],today:"Oggi",clear:"Cancella",weekStart:1,format:"dd.mm.yyyy"}}(jQuery);
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.fr.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.fr={days:["dimanche","lundi","mardi","mercredi","jeudi","vendredi","samedi","dimanche"],daysShort:["dim.","lun.","mar.","mer.","jeu.","ven.","sam.","dim."],daysMin:["d","l","ma","me","j","v","s","d"],months:["janvier","février","mars","avril","mai","juin","juillet","août","septembre","octobre","novembre","décembre"],monthsShort:["janv.","févr.","mars","avril","mai","juin","juil.","août","sept.","oct.","nov.","déc."],today:"Aujourd'hui",clear:"Effacer",weekStart:1,format:"dd/mm/yyyy"}}(jQuery);
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.ka.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.ka={days:["კვირა","ორშაბათი","სამშაბათი","ოთხშაბათი","ხუთშაბათი","პარასკევი","შაბათი","კვირა"],daysShort:["კვი","ორშ","სამ","ოთხ","ხუთ","პარ","შაბ","კვი"],daysMin:["კვ","ორ","სა","ოთ","ხუ","პა","შა","კვ"],months:["იანვარი","თებერვალი","მარტი","აპრილი","მაისი","ივნისი","ივლისი","აგვისტო","სექტემბერი","ოქტომები","ნოემბერი","დეკემბერი"],monthsShort:["იან","თებ","მარ","აპრ","მაი","ივნ","ივლ","აგვ","სექ","ოქტ","ნოე","დეკ"],today:"დღეს",clear:"გასუფთავება",weekStart:1,format:"dd.mm.yyyy"}}(jQuery);
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.el.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.el={days:["Κυριακή","Δευτέρα","Τρίτη","Τετάρτη","Πέμπτη","Παρασκευή","Σάββατο","Κυριακή"],daysShort:["Κυρ","Δευ","Τρι","Τετ","Πεμ","Παρ","Σαβ","Κυρ"],daysMin:["Κυ","Δε","Τρ","Τε","Πε","Πα","Σα","Κυ"],months:["Ιανουάριος","Φεβρουάριος","Μάρτιος","Απρίλιος","Μάιος","Ιούνιος","Ιούλιος","Αύγουστος","Σεπτέμβριος","Οκτώβριος","Νοέμβριος","Δεκέμβριος"],monthsShort:["Ιαν","Φεβ","Μαρ","Απρ","Μάι","Ιουν","Ιουλ","Αυγ","Σεπ","Οκτ","Νοε","Δεκ"],today:"Σήμερα",clear:"Καθαρισμός",weekStart:1,format:"d/m/yyyy"}}(jQuery);
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/locales/bootstrap-datepicker.et.min.js:
--------------------------------------------------------------------------------
1 | !function(a){a.fn.datepicker.dates.et={days:["Pühapäev","Esmaspäev","Teisipäev","Kolmapäev","Neljapäev","Reede","Laupäev","Pühapäev"],daysShort:["Pühap","Esmasp","Teisip","Kolmap","Neljap","Reede","Laup","Pühap"],daysMin:["P","E","T","K","N","R","L","P"],months:["Jaanuar","Veebruar","Märts","Aprill","Mai","Juuni","Juuli","August","September","Oktoober","November","Detsember"],monthsShort:["Jaan","Veebr","Märts","Apr","Mai","Juuni","Juuli","Aug","Sept","Okt","Nov","Dets"],today:"Täna",clear:"Tühjenda",weekStart:1,format:"dd.mm.yyyy"}}(jQuery);
--------------------------------------------------------------------------------
/server/client/templates/wechat-live-server.js:
--------------------------------------------------------------------------------
1 |
2 | Template.wechatLiveMain.helpers({
3 | chat_records: function () {
4 | return ChatRecords.liveItems();
5 | },
6 |
7 | today: function() {
8 | return new Date().Format("yyyy-MM-dd");
9 | }
10 | });
11 |
12 | Template.wechatLiveMain.onRendered(function () {
13 | Session.set('detail_mode','live');
14 | var div = document.getElementById('list_content_ul');
15 | var iHeight = document.documentElement.clientHeight || document.body.clientHeight;
16 | var header = document.getElementById('panel_heading');
17 | div.style.height = iHeight - header.offsetHeight - 15 + "px";
18 |
19 | div.scrollTop = div.scrollHeight;
20 | });
21 |
22 |
23 |
--------------------------------------------------------------------------------
/server/lib/top-collections.js:
--------------------------------------------------------------------------------
1 | TopRecords = new Mongo.Collection("wx_top_records");
2 | //nickId, chatCount, lastContent
3 |
4 | TopRecords.addOrInsertRecord = function (nickId, lastContent) {
5 | //console.log("......nickId:"+ nickId+ " "+lastContent);
6 | var topR = TopRecords.findOne({nickId: nickId});
7 | var result;
8 | if (topR === undefined) {
9 | var count = ChatRecords.rank(nickId);
10 | result = TopRecords.insert({nickId: nickId, chatCount: count, lastContent: lastContent});
11 | } else {
12 | result = TopRecords.update({nickId: nickId}, {
13 | nickId: nickId,
14 | chatCount: topR.chatCount + 1,
15 | lastContent: lastContent
16 | });
17 | }
18 | }
19 |
20 |
--------------------------------------------------------------------------------
/server/client/head.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
8 |
9 | 直播“下一代智能操作系统开发讨论”
10 |
11 |
12 |
13 |
14 |
15 |
16 |
18 |
19 |
--------------------------------------------------------------------------------
/server/client/templates/top-activity.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
16 |
17 |
18 | {{#each users}}
19 | {{> userItem}}
20 | {{/each}}
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | {{chatCount}}
31 | {{nickId}}
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/server/client/templates/user-records.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
15 |
16 |
17 |
18 | {{#each records this.nickId}}
19 | {{> userRecordItem}}
20 | {{/each}}
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 | {{createdAtHuman createdAt}}
32 |
33 |
34 |
35 |
36 | {{content}}
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/phone/res/xml/wxlive_accessibility_service_config.xml:
--------------------------------------------------------------------------------
1 |
2 |
21 |
28 |
29 |
--------------------------------------------------------------------------------
/server/.meteor/versions:
--------------------------------------------------------------------------------
1 | accounts-base@1.2.0
2 | accounts-password@1.1.1
3 | autoupdate@1.2.1
4 | base64@1.0.3
5 | binary-heap@1.0.3
6 | blaze@2.1.2
7 | blaze-tools@1.0.3
8 | boilerplate-generator@1.0.3
9 | callback-hook@1.0.3
10 | check@1.0.5
11 | ddp@1.1.0
12 | deps@1.0.7
13 | ejson@1.0.6
14 | email@1.0.6
15 | fastclick@1.0.3
16 | geojson-utils@1.0.3
17 | html-tools@1.0.4
18 | htmljs@1.0.4
19 | http@1.1.0
20 | id-map@1.0.3
21 | iron:controller@1.0.7
22 | iron:core@1.0.7
23 | iron:dynamic-template@1.0.7
24 | iron:layout@1.0.7
25 | iron:location@1.0.7
26 | iron:middleware-stack@1.0.7
27 | iron:router@1.0.7
28 | iron:url@1.0.7
29 | jparker:crypto-core@0.1.0
30 | jparker:crypto-md5@0.1.1
31 | jquery@1.11.3_2
32 | json@1.0.3
33 | launch-screen@1.0.2
34 | livedata@1.0.13
35 | localstorage@1.0.3
36 | logging@1.0.7
37 | meteor@1.1.6
38 | meteor-platform@1.2.2
39 | minifiers@1.1.5
40 | minimongo@1.0.8
41 | mobile-status-bar@1.0.3
42 | mongo@1.1.0
43 | npm-bcrypt@0.7.8_2
44 | observe-sequence@1.0.6
45 | ordered-dict@1.0.3
46 | random@1.0.3
47 | reactive-dict@1.1.0
48 | reactive-var@1.0.5
49 | reload@1.1.3
50 | retry@1.0.3
51 | routepolicy@1.0.5
52 | service-configuration@1.0.4
53 | session@1.1.0
54 | sha@1.0.3
55 | spacebars@1.0.6
56 | spacebars-compiler@1.0.6
57 | srp@1.0.3
58 | templating@1.1.1
59 | tracker@1.0.7
60 | ui@1.0.6
61 | underscore@1.0.3
62 | url@1.0.4
63 | webapp@1.2.0
64 | webapp-hashing@1.0.3
65 |
--------------------------------------------------------------------------------
/phone/src/mobi/espier/lgc/util/WeakHandlerTemplate.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2010~2014 FMSoft (Espier Studio)
3 | *
4 | * This program is free software: you can redistribute it and/or modify it under the terms of the
5 | * GNU Affero General Public License as published by the Free Software Foundation, either version 3
6 | * of the License, or (at your option) any later version.
7 | *
8 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
9 | * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 | * Affero General Public License for more details.
11 | *
12 | * You should have received a copy of the GNU Affero General Public License along with this program.
13 | * If not, see .
14 | */
15 | package mobi.espier.lgc.util;
16 |
17 | import java.lang.ref.WeakReference;
18 |
19 | import android.os.Handler;
20 |
21 | public class WeakHandlerTemplate extends Handler {
22 | private final WeakReference mContext;
23 |
24 | public WeakHandlerTemplate(T context) {
25 | mContext = new WeakReference(context);
26 | }
27 |
28 | public WeakHandlerTemplate(T context, Callback cb) {
29 | super(cb);
30 | mContext = new WeakReference(context);
31 | }
32 |
33 | protected T getObject() {
34 | if (mContext != null) return mContext.get();
35 | return null;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/server/client/templates/history.js:
--------------------------------------------------------------------------------
1 |
2 | HISTORY_RECORDS_SIZE = "historyBlockSize";
3 | HISTORY_DATE = "historyDate";
4 |
5 | Session.setDefault(HISTORY_RECORDS_SIZE, FIRST_BLOCK_SIZE);
6 |
7 | Template.history.helpers({
8 | chat_records: function () {
9 | return ChatRecords.findBlockHistoryItemsByDay(this.time, ASC_SORT,
10 | Session.get(HISTORY_RECORDS_SIZE));
11 | }
12 | });
13 |
14 | Template.history.events({
15 | 'scroll ul': function (event) {
16 | var div = document.getElementById("list_content_ul");
17 |
18 | if (div.scrollTop == (div.scrollHeight-div.offsetHeight)) {
19 | console.log('screenTop=' + div.scrollTop + ' get more');
20 | Session.set(HISTORY_RECORDS_SIZE, Session.get(HISTORY_RECORDS_SIZE) + INCREASE_BLOCK_SIZE);
21 |
22 | }
23 | }
24 | });
25 |
26 | Template.history.rendered = function() {
27 | this.autorun(function() {
28 | Meteor.subscribe("recordsInDay", Session.get(HISTORY_DATE), ASC_SORT,
29 | Session.get(HISTORY_RECORDS_SIZE));
30 | });
31 | };
32 |
33 | Template.history.onRendered(function () {
34 | Session.set('detail_mode','history');
35 | var div = document.getElementById('list_content_ul');
36 | var iHeight = document.documentElement.clientHeight || document.body.clientHeight;
37 | var header = document.getElementById('panel_heading');
38 | div.style.height = iHeight - header.offsetHeight - 15 + "px";
39 | });
40 |
--------------------------------------------------------------------------------
/phone/res/values-zh-rCN/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 | 群聊直播
13 | 群聊直播描述
14 | 通知服务 : 正在运行
15 | 通知服务 : 已停止
16 | 辅助功能
17 | WebSocket URL :
18 | "ws://ip:port/xxx"
19 | 用户名 :
20 | 密码 :
21 | 启动
22 | 停止
23 | "参数不能为空"
24 | "登录失败 : "
25 |
26 | "正在连接服务器 ..."
27 | "服务器连接成功 ..."
28 | "用户登录 ..."
29 | "用户登录成功 ..."
30 | "用户登录失败 ..."
31 | "断开连接原因 : "
32 | "上传数据 : "
33 |
34 |
35 |
--------------------------------------------------------------------------------
/server/client/templates/top-activity.js:
--------------------------------------------------------------------------------
1 | USER_RANK_SIZE = "userRankSize";
2 | Session.setDefault(USER_RANK_SIZE, FIRST_BLOCK_SIZE);
3 |
4 | Template.userRank.helpers({
5 | users: function () {
6 | return TopRecords.find({}, {sort: {chatCount: DESC_SORT}}).map(
7 | function (doc, index, cursor) {
8 | var i = _.extend(doc, {index: index});
9 | return i;
10 | });
11 | }
12 | });
13 |
14 | Template.userRank.events({
15 | 'scroll ul': function (event) {
16 | var div = document.getElementById("list_content_ul");
17 |
18 | if (div.scrollTop == (div.scrollHeight-div.offsetHeight)) {
19 | if (TopRecords.find().count() >= Session.get(USER_RANK_SIZE))
20 | Session.set(USER_RANK_SIZE, Session.get(USER_RANK_SIZE) + INCREASE_BLOCK_SIZE);
21 | }
22 | }
23 | });
24 |
25 | Template.userRank.rendered = function() {
26 | this.autorun(function() {
27 | Meteor.subscribe("userRanks", DESC_SORT, Session.get(USER_RANK_SIZE));
28 | });
29 | };
30 |
31 | Template.userRank.onRendered(function () {
32 | var self = this;
33 | userIndex = 0;
34 | var div = self.find('#list_content_ul');
35 | var iHeight = document.documentElement.clientHeight || document.body.clientHeight;
36 | var header = self.find('#panel_heading');
37 | div.style.height = iHeight - 5 - header.offsetHeight + "px";
38 | });
39 |
40 | Template.userItem.helpers({
41 | bg: function (index) {
42 | return index % 2 == 0 ? " list-group-item-info" : "";
43 | }
44 | });
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Live Group Chat
2 |
3 | Live Group Chat can broadcast the group chat records of WeChat (or other Instant Messaging apps) to a web page.
4 |
5 | Live Group Chat contains an Android app and a web site. The former hooks to the Android notification system and send the chat records to the web site via WebSocket; the latter receives the chat records and shows them in a web page.
6 |
7 | The web site is developed by using [Meteor](https://www.meteor.com).
8 |
9 | For a live demonstration, please visit [NGOS live discussion site](http://ngsos.fullstackengineer.net/).
10 |
11 | ## Usage
12 | ### Android app
13 | * Install Live Group Chat app.
14 | * Enable Notification service (Settings->Acessibility->Live Group Chat).
15 | * Input correct websocket url, username and password.
16 | * Click Start button.
17 |
18 | ### Web site
19 | #### Build meteor application bundle
20 | ``` shell
21 | $ cd live-group-chat/server
22 | $ meteor build dest_dir # the output directory will contain just a tarball that includes everything necessary to run the application server. (server.tar.gz)
23 | ```
24 | #### Deploy application on the internet
25 | * External dependency:[Node.js 0.10.36](http://nodejs.org/dist/v0.10.36/), [MongoDB](http://www.mongodb.org/downloads).
26 | * To run the application:
27 | ``` shell
28 | $ (cd programs/server && npm install)
29 | $ export PORT="3000"
30 | $ export MONGO_URL='mongodb://user:password@host:port/databasename'
31 | $ export ROOT_URL='http://example.com'
32 | $ export MAIL_URL='smtp://user:password@mailhost:port/'
33 | $ node main.js # PORT="80", need root privileges
34 | ```
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/server/client/templates/history.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
{{date}}
10 |
11 |
16 |
31 |
32 |
33 |
34 | {{#each chat_records}}
35 | {{> chat_record_detail}}
36 | {{/each}}
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/server/client/templates/wechat-live-server.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
33 |
34 |
35 | {{#each chat_records}}
36 | {{> chat_record_detail}}
37 | {{/each}}
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/server/client/templates/chat-record-detail.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by xwyan on 15/4/17.
3 | */
4 | Template.chat_record_detail.helpers({
5 | createdAtHuman : function(createdAt) {
6 | if (Session.get('detail_mode') == 'live') {
7 | var div = document.getElementById("list_content_ul");
8 | if (div && div.scrollTop + div.offsetHeight >= div.scrollHeight)
9 | Session.set("scrollToBottom", true);
10 | else
11 | Session.set("scrollToBottom", false);
12 | }
13 | return ChatRecords.date(createdAt, "hh:mm");
14 | }
15 | });
16 |
17 | function Linkify(inputText) {
18 | //URLs starting with http://, https://, or ftp://
19 | var replacePattern1 = /(\b(https?|ftp):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gim;
20 | var replacedText = inputText.replace(replacePattern1, '$1 ');
21 |
22 | //URLs starting with www. (without // before it, or it'd re-link the ones done above)
23 | var replacePattern2 = /(^|[^\/])(www\.[\S]+(\b|$))/gim;
24 | var replacedText = replacedText.replace(replacePattern2, '$1$2 ');
25 |
26 | //Change email addresses to mailto:: links
27 | var replacePattern3 = /(\w+@[a-zA-Z_]+?\.[a-zA-Z]{2,6})/gim;
28 | var replacedText = replacedText.replace(replacePattern3, '$1 ');
29 |
30 | return replacedText;
31 | }
32 |
33 | Template.chat_record_detail.onRendered (function () {
34 | var detail = this.$('div.content');
35 | var html = Linkify (detail.text ());
36 | detail.html (html);
37 |
38 | if(Session.get('detail_mode') == 'live' && Session.get("scrollToBottom")) {
39 | var div = document.getElementById("list_content_ul");
40 | div.scrollTop = div.scrollHeight;
41 | }
42 | });
43 |
44 |
--------------------------------------------------------------------------------
/server/lib/router.js:
--------------------------------------------------------------------------------
1 |
2 | Router.configure({
3 | waitOn: function() {
4 | return [Meteor.subscribe('liveRecords', LIVE_TIME)];
5 | }
6 | });
7 |
8 | Router.map(function() {
9 | this.route('wechatLiveMain', {
10 | path: '/'
11 | });
12 |
13 | this.route('userRank', {
14 | path: '/users',
15 | onBeforeAction: function() {
16 | Meteor.subscribe('userRanks', DESC_SORT, FIRST_BLOCK_SIZE);
17 | this.next();
18 | },
19 |
20 | action: function() {
21 | this.render();
22 | }
23 | });
24 |
25 | this.route('userRecords', {
26 | path: '/users/:nickId',
27 |
28 | onBeforeAction: function() {
29 | Session.set(USER_RECORDS_SIZE, FIRST_BLOCK_SIZE);
30 | Session.set(HISTORY_NICKID, this.params.nickId);
31 | Meteor.subscribe('recordsInNick', this.params.nickId, ASC_SORT,FIRST_BLOCK_SIZE);
32 | this.next();
33 | },
34 |
35 | data: function() {
36 | return {nickId: this.params.nickId};
37 | },
38 |
39 | action: function() {
40 | this.render();
41 | }
42 | });
43 |
44 |
45 | this.route('history', {
46 | path: '/history/:date',
47 |
48 | onBeforeAction: function() {
49 | time = new Date(this.params.date).getTime();
50 | Session.set(HISTORY_RECORDS_SIZE, FIRST_BLOCK_SIZE);
51 | Session.set(HISTORY_DATE, time);
52 | Meteor.subscribe('recordsInDay', time, ASC_SORT, FIRST_BLOCK_SIZE);
53 | this.next();
54 | },
55 |
56 | data: function() {
57 | return {time: new Date(this.params.date).getTime(), date: this.params.date};
58 | },
59 |
60 | action: function() {
61 | this.render();
62 | }
63 | })
64 |
65 | this.route('about', {
66 | path: '/about'
67 | });
68 | });
69 |
--------------------------------------------------------------------------------
/server/client/templates/about.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
智能系统百家谈
25 |
26 |
27 | “智能系统百家谈”是由下一代智能操作系统技术联盟维护的微信公众号,主要用于发表高手们的技术文章、活动总结、通知、投票等,更多功能还在开发中。在微信中搜索公众号
28 | discNGOS
29 | 或扫一扫下面的二维码关注。
30 |
31 |
32 |
33 |
34 |
35 |
36 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/server/client/templates/user-records.js:
--------------------------------------------------------------------------------
1 | USER_RECORDS_SIZE = "userBlockSize";
2 | HISTORY_NICKID = "historyNickId";
3 |
4 | Session.setDefault(USER_RECORDS_SIZE, FIRST_BLOCK_SIZE);
5 |
6 | Template.userRecords.helpers({
7 | records : function(id) {
8 | return ChatRecords.find({nickId:id}, {sort: {createdAt: ASC_SORT}}).map(function (doc, index, cursor) {
9 | var i = _.extend(doc, {index: index});
10 | return i;
11 | });
12 | }
13 | });
14 |
15 | Template.userRecords.events({
16 | 'scroll ul': function (event) {
17 | var div = document.getElementById("list_content_ul");
18 |
19 | if (div.scrollTop == (div.scrollHeight-div.offsetHeight)) {
20 | Session.set(USER_RECORDS_SIZE, Session.get(USER_RECORDS_SIZE) + INCREASE_BLOCK_SIZE);
21 | }
22 | }
23 | });
24 |
25 | Template.userRecords.rendered = function() {
26 | this.autorun(function() {
27 | Meteor.subscribe("recordsInNick", Session.get(HISTORY_NICKID),
28 | ASC_SORT, Session.get(USER_RECORDS_SIZE));
29 | });
30 | };
31 |
32 |
33 | Template.userRecords.onRendered(function(){
34 | var self=this;
35 | var div = self.find('#list_content_ul');
36 | var iHeight = document.documentElement.clientHeight||document.body.clientHeight;
37 | var header = self.find('#panel_heading');
38 | div.style.height = iHeight- 15 -header.offsetHeight+"px";
39 | var title_div = self.find('#title');
40 | var container = self.find('#container');
41 | title_div.style.width = container.offsetWidth-150 +"px";
42 | });
43 |
44 |
45 | Template.userRecordItem.helpers({
46 | createdAtHuman : function(createdAt) {
47 | return ChatRecords.date(createdAt,"MM-dd hh:mm");
48 | },
49 | bg:function(index){
50 | return index % 2 == 0 ? "list-group-item-info" : "";
51 | }
52 | });
53 |
54 | Template.userRecordItem.onRendered (function () {
55 | var detail = this.$('div.content');
56 | var html = Linkify (detail.text ());
57 | detail.html (html);
58 |
59 | });
60 |
--------------------------------------------------------------------------------
/server/server/server.js:
--------------------------------------------------------------------------------
1 | var timeInterval = 24*60*60*1000;
2 |
3 | Meteor.publish('recordsInDay', function(dayms, sort, limitSize) {
4 | var time = beginTime(dayms);
5 | return ChatRecords.find({content: {$regex: /^(?!!|!).*$/}, createdAt: {$lt: time+timeInterval, $gte:time}},
6 | {sort: {createdAt : sort}, limit : limitSize});
7 | });
8 |
9 | Meteor.publish('recordsInNick',function(nickid, sort, limitSize) {
10 | return ChatRecords.find({content: {$regex: /^(?!!|!).*$/}, nickId: nickid},
11 | {sort: {createdAt : sort}, limit : limitSize});
12 | });
13 |
14 | Meteor.publish('liveRecords', function(time) {
15 | var result = ChatRecords.find({content: {$regex: /^(?!!|!).*$/}, createdAt: {$lt : time}}, {sort: {createdAt : -1},
16 | limit : 20});
17 | var resultArray = result.fetch();
18 | if (resultArray.length != 0) {
19 | time = resultArray[resultArray.length-1].createdAt;
20 | }
21 | return ChatRecords.find({content: {$regex: /^(?!!|!).*$/}, createdAt: {$gte : time}}, {sort: {createdAt : 1}});
22 | });
23 |
24 | Meteor.publish("userRanks", function (sort, limit) {
25 | return TopRecords.find({nickId: {$ne: ''}}, {sort: {chatCount: sort}, limit: limit});
26 | });
27 |
28 | Accounts.onCreateUser(function(options, user) {
29 | if (options.profile)
30 | user.profile = options.profile;
31 |
32 | var admin = JSON.parse(Assets.getText("admin.txt"));
33 | user.admin = (user.username === admin.username);
34 |
35 | return user;
36 | });
37 |
38 | if (Meteor.isServer) {
39 | Meteor.startup(function () {
40 | // code to run on server at startup
41 | try {
42 | var admin = JSON.parse(Assets.getText("admin.txt"));
43 |
44 | if(!Meteor.users.findOne({username: admin.username})) {
45 | Accounts.createUser({
46 | username: admin.username,
47 | password: admin.password
48 | });
49 | } else {
50 | console.log('admin exists');
51 | }
52 | } catch (error) {
53 | console.log(error.reason);
54 | }
55 |
56 | ChatRecords.find({createdAt: {$gte:new Date().getTime()}}).observe({
57 | added:function(record){
58 | TopRecords.addOrInsertRecord(record.nickId,record.content);
59 | }
60 | });
61 |
62 | });
63 | }
64 |
--------------------------------------------------------------------------------
/phone/src/mobi/espier/lgc/data/LgcDBHelper.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2010~2014 FMSoft (Espier Studio)
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Affero General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Affero General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Affero General Public License
15 | * along with this program. If not, see .
16 | *
17 | */
18 | package mobi.espier.lgc.data;
19 |
20 | import android.content.Context;
21 | import android.database.sqlite.SQLiteDatabase;
22 | import android.database.sqlite.SQLiteOpenHelper;
23 |
24 | public class LgcDBHelper extends SQLiteOpenHelper {
25 |
26 | private static final int DB_VERSION = 1;
27 | private static final String DB_NAME = "wxlive.db";
28 | public static final String TABLE_NAME = "notifications";
29 |
30 | public LgcDBHelper(Context context) {
31 | super(context, DB_NAME, null, DB_VERSION);
32 | }
33 |
34 | @Override
35 | public void onCreate(SQLiteDatabase db) {
36 | db.execSQL("CREATE TABLE " + TABLE_NAME + " (" + LgcProvider.DataColumns._ID
37 | + " INTEGER PRIMARY KEY, " + LgcProvider.DataColumns.NAME + " TEXT, "
38 | + LgcProvider.DataColumns.CONTENT + " TEXT, " + LgcProvider.DataColumns.TYPE
39 | + " INTEGER, " + LgcProvider.DataColumns.TIME + " INTEGER, "
40 | + LgcProvider.DataColumns.HASH + " TEXT, " + LgcProvider.DataColumns.SYNC
41 | + " INTEGER " + " );");
42 | }
43 |
44 | @Override
45 | public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
46 | db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
47 | onCreate(db);
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/phone/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
21 |
22 | Live Group Chat
23 | Live chat group description.
24 | Notification service : Running
25 | Notification service : Stopped
26 | Accessibility
27 | WebSocket URL :
28 | "ws://ip:port/xxx"
29 | Username :
30 | Password :
31 | Start
32 | Stop
33 | "Parameters must not be null"
34 | "Login failed : "
35 |
36 |
37 | "connect to server ..."
38 | "connect ok ..."
39 | "user login ..."
40 | "user login ok ..."
41 | "user login failed ..."
42 | "disconnect reason : "
43 | "update data : "
44 |
45 |
46 |
--------------------------------------------------------------------------------
/server/lib/collections.js:
--------------------------------------------------------------------------------
1 | ChatRecords = new Mongo.Collection("wx_chat_records");
2 | //nickId, content, contentType, createdAt, hash, comment, commentId, commentAt
3 |
4 | LIVE_TIME = new Date().getTime();
5 | FIRST_BLOCK_SIZE = 30;
6 | INCREASE_BLOCK_SIZE = 20;
7 |
8 | DESC_SORT = -1;
9 | ASC_SORT = 1;
10 |
11 | var timeInterval = 24*60*60*1000;
12 |
13 | beginTime = function(ms) {
14 | var date = new Date(ms);
15 | return ms - date.getHours()*60*60*1000 - date.getMinutes()*60*1000 - date.getSeconds()*1000 - date.getMilliseconds();
16 |
17 | }
18 |
19 | ChatRecords.allow({
20 | insert: function (userId) {
21 | var user = Meteor.users.findOne(userId);
22 | return user && user.admin;
23 | },
24 | update: function (userId) {
25 | var user = Meteor.users.findOne(userId);
26 | return user && user.admin;
27 | }
28 | });
29 |
30 | ChatRecords.liveItems = function() {
31 | time = LIVE_TIME;
32 | var starttime = beginTime(time);
33 | var result = ChatRecords.find({createdAt: {$lt : time, $gte: starttime}}, {sort: {createdAt : DESC_SORT},
34 | limit : FIRST_BLOCK_SIZE});
35 | var resultArray = result.fetch();
36 | if (resultArray.length != 0) {
37 | time = resultArray[resultArray.length-1].createdAt;
38 | }
39 | return ChatRecords.find({createdAt: {$gte : time}}, {sort: {createdAt : ASC_SORT}});
40 | }
41 |
42 | ChatRecords.findBlockHistoryItemsByDay = function(msInDay, sort, limitSize) {
43 | var time = beginTime(msInDay);
44 | return ChatRecords.find({createdAt: {$lt : time + timeInterval, $gte: time}}, {sort: {createdAt : sort},
45 | limit: limitSize});
46 | }
47 |
48 | ChatRecords.rank = function(nickId) {
49 | return ChatRecords.find({nickId: nickId}).count();
50 | }
51 |
52 | Date.prototype.Format = function (fmt) { //author: meizz
53 | var o = {
54 | "M+": this.getMonth() + 1, //月份
55 | "d+": this.getDate(), //日
56 | "h+": this.getHours(), //小时
57 | "m+": this.getMinutes(), //分
58 | "s+": this.getSeconds(), //秒
59 | "q+": Math.floor((this.getMonth() + 3) / 3), //季度
60 | "S": this.getMilliseconds() //毫秒
61 | };
62 | if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
63 | for (var k in o)
64 | if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
65 | return fmt;
66 | }
67 |
68 | ChatRecords.date = function(ms,format) {
69 | return new Date(ms).Format(format);
70 | }
71 |
--------------------------------------------------------------------------------
/server/client/templates/wechat-live-server.css:
--------------------------------------------------------------------------------
1 | /* CSS declarations go here */
2 | body {
3 | font-family: sans-serif;
4 | background-color: white;
5 | background-attachment: fixed;
6 |
7 | position: absolute;
8 | top: 0;
9 | bottom: 0;
10 | left: 0;
11 | right: 0;
12 |
13 | padding: 0;
14 | margin: 0;
15 | }
16 |
17 | .item{
18 | width:100%;
19 | }
20 |
21 | #container {
22 | max-width: 768px;
23 | background:#ecefef;
24 | margin: 0 auto;
25 | min-height: 100%;
26 | position:relative;
27 | }
28 |
29 | .nickId {
30 | font-size: 14px;
31 | margin-bottom:5px;
32 | width:50%;
33 | background: transparent;
34 | color:#666666;
35 | float:left;
36 | }
37 |
38 | .createdAt {
39 | font-size: 12px;
40 | margin-bottom:5px;
41 | float:right;
42 | width:50%;
43 | background: transparent;
44 | text-align:right;
45 | color:#666666;
46 | }
47 |
48 | .content {
49 | font-size: 16px;
50 | padding:10px;
51 | border:1px solid;
52 | border-color:#b3b3b3;
53 | border-radius:7px;
54 | float:left;
55 | margin-bottom:25px;
56 | background:white;
57 | word-break:break-all;
58 | }
59 |
60 | #panel_heading {
61 | margin: 0;
62 | background: -webkit-gradient(linear, 0% 0%, 0% 100%,from(#573e7d ), to(#6f5499));
63 | background: -moz-linear-gradient(top, #573e7d, #6f5499);
64 | background: -o-linear-gradient(top,#573e7d, #6f5499);
65 | color: #ffffff;
66 | padding: 5px 15px 5px 15px;
67 | min-height: 50px;
68 | position: relative;
69 | text-align:center;
70 | vertical-align:middle;
71 | }
72 | #panel_body {
73 | padding: 0;
74 | margin: 0;
75 | }
76 |
77 |
78 | #title {
79 | font-size: 18px;
80 | margin: 0;
81 | min-height: 40px;
82 | line-height: 40px;
83 | text-align: center;
84 | display: inline-block;
85 | white-space:nowrap;
86 | text-overflow:ellipsis;
87 | -o-text-overflow:ellipsis;
88 | overflow:hidden;
89 | }
90 |
91 | #img_title_icon{
92 | width: 30px;
93 | height: 22px;
94 | }
95 |
96 | ul {
97 | margin-left:20px;
98 | padding: 0;
99 | padding-right: 20px;
100 | background: transparent;
101 | height: 650px;
102 | overflow-x:hidden;
103 | overflow-y:scroll;
104 | }
105 |
106 | .top_ul {
107 | margin-left:0px;
108 | padding: 0;
109 | padding-right: 2px;
110 | background: transparent;
111 | word-break: break-all;
112 | height: 650px;
113 | overflow-x:hidden;
114 | overflow-y:scroll;
115 | }
116 |
117 | .span_icon {
118 | font-size: 26px;
119 | text-align: center;
120 | }
121 |
122 | #btn_glyphicon {
123 | color: white;
124 | }
125 |
--------------------------------------------------------------------------------
/phone/src/mobi/espier/lgc/util/SecurityUtils.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2010~2014 FMSoft (Espier Studio)
3 | *
4 | * This program is free software: you can redistribute it and/or modify it under the terms of the
5 | * GNU Affero General Public License as published by the Free Software Foundation, either version 3
6 | * of the License, or (at your option) any later version.
7 | *
8 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
9 | * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 | * Affero General Public License for more details.
11 | *
12 | * You should have received a copy of the GNU Affero General Public License along with this program.
13 | * If not, see .
14 | */
15 |
16 | package mobi.espier.lgc.util;
17 |
18 | import java.security.InvalidKeyException;
19 | import java.security.MessageDigest;
20 | import java.security.NoSuchAlgorithmException;
21 |
22 | import javax.crypto.Mac;
23 | import javax.crypto.spec.SecretKeySpec;
24 |
25 |
26 | public class SecurityUtils {
27 | private static final String TAG = "SecrityUtils";
28 |
29 | public static String hmacMd5(String data, String key) {
30 | Mac mac;
31 | try {
32 | mac = Mac.getInstance("HmacMD5");
33 | SecretKeySpec sk = new SecretKeySpec(key.getBytes(), mac.getAlgorithm());
34 | mac.init(sk);
35 | byte[] result = mac.doFinal(data.getBytes());
36 |
37 | StringBuilder sb = new StringBuilder();
38 | for (byte b : result) {
39 | sb.append(String.format("%02x", b));
40 | }
41 |
42 | return sb.toString();
43 |
44 | } catch (NoSuchAlgorithmException e) {} catch (InvalidKeyException e) {}
45 |
46 | return "";
47 | }
48 |
49 | public static String md5(String key) {
50 | return md5(key.getBytes());
51 | }
52 |
53 | public static String md5(byte[] input) {
54 | String cacheKey = null;
55 | try {
56 | final MessageDigest mDigest = MessageDigest.getInstance("MD5");
57 | mDigest.update(input);
58 | cacheKey = bytesToHexString(mDigest.digest());
59 | } catch (NoSuchAlgorithmException e) {}
60 | return cacheKey;
61 | }
62 |
63 | private static String bytesToHexString(byte[] bytes) {
64 | // http://stackoverflow.com/questions/332079
65 | StringBuilder sb = new StringBuilder();
66 | for (int i = 0; i < bytes.length; i++) {
67 | String hex = Integer.toHexString(0xFF & bytes[i]);
68 | if (hex.length() == 1) {
69 | sb.append('0');
70 | }
71 | sb.append(hex);
72 | }
73 | return sb.toString();
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/phone/src/mobi/espier/lgc/util/LgcUtils.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2010~2014 FMSoft (Espier Studio)
3 | *
4 | * This program is free software: you can redistribute it and/or modify it under the terms of the
5 | * GNU Affero General Public License as published by the Free Software Foundation, either version 3
6 | * of the License, or (at your option) any later version.
7 | *
8 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
9 | * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 | * Affero General Public License for more details.
11 | *
12 | * You should have received a copy of the GNU Affero General Public License along with this program.
13 | * If not, see .
14 | */
15 | package mobi.espier.lgc.util;
16 |
17 |
18 | import android.content.Context;
19 |
20 | public class LgcUtils {
21 | public static final int UPLOAD_DELAYED = 30000;
22 | public static final int UPLOAD_LIMIT = 10;
23 |
24 | public static final String KEY_UPLOAD_DELAYED = "key_upload_delayed";
25 | public static final String KEY_WEBSOCKET_URL = "key_websocket_url";
26 | public static final String KEY_USERNAME = "key_username";
27 | public static final String KEY_PASSWORD = "key_password";
28 | public static final String KEY_REASON = "key_reason";
29 | public static final String KEY_METEOR_LOGIN_RESULT = "key_meteor_login_result";
30 | public static final String KEY_METEOR_STATE = "key_meteor_state";
31 |
32 | public static final String ACTION_DATA_CHANGE = "action_data_change";
33 | public static final String ACTION_METEOR_LOGIN_RESULT = "action_meteor_login_result";
34 | public static final String ACTION_METEOR_STATE = "action_meteor_state";
35 |
36 | public static final int METEOR_LOGIN_FAILED = 0;
37 | public static final int METEOR_LOGIN_OK = 1;
38 |
39 | public static int getUploadDelayed(Context context) {
40 | return PreferencesUtil.getInt(context, KEY_UPLOAD_DELAYED, UPLOAD_DELAYED);
41 | }
42 |
43 | public static void setUploadDelayed(Context context, int delayed) {
44 | PreferencesUtil.putInt(context, KEY_UPLOAD_DELAYED, delayed);
45 | }
46 |
47 | public static String getWebsocketUrl(Context context, String defUrl) {
48 | return PreferencesUtil.getString(context, KEY_WEBSOCKET_URL, defUrl);
49 | }
50 |
51 | public static void setWebsocketUrl(Context context, String url) {
52 | PreferencesUtil.putString(context, KEY_WEBSOCKET_URL, url);
53 | }
54 |
55 | public static String getUsername(Context context) {
56 | return PreferencesUtil.getString(context, KEY_USERNAME, null);
57 | }
58 |
59 | public static void setUsername(Context context, String username) {
60 | PreferencesUtil.putString(context, KEY_USERNAME, username);
61 | }
62 |
63 | public static String getPasword(Context context) {
64 | return PreferencesUtil.getString(context, KEY_PASSWORD, null);
65 | }
66 |
67 | public static void setPasswrod(Context context, String password) {
68 | PreferencesUtil.putString(context, KEY_PASSWORD, password);
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/phone/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
21 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
42 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
65 |
66 |
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/phone/src/mobi/espier/lgc/util/LogUtils.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2010~2014 FMSoft (Espier Studio)
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Affero General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Affero General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Affero General Public License
15 | * along with this program. If not, see .
16 | *
17 | */
18 | package mobi.espier.lgc.util;
19 |
20 | import mobi.espier.lgc.BuildConfig;
21 | import android.util.Log;
22 |
23 | /**
24 | * API for sending log output.
25 | *
26 | * Generally, use the LogUtils.v() LogUtils.d() LogUtils.i() LogUtils.w() and LogUtils.e() methods.
27 | *
28 | * public static final boolean DEBUG = Log.isLoggable(TAG, Log.VERBOSE) || BuildConfig.DEBUG;
29 | *
30 | * By default(release), LogUtils.DEBUG is false, only print the log which priority > Log.INFO. If
31 | * you want to show all log. You can use the following command : adb shell setprop
32 | * log.tag.WxLiveLogUtils VERBOSE
33 | *
34 | *
35 | */
36 | final public class LogUtils {
37 | private static final String TAG = "WxLiveLogUtils";
38 |
39 | public static final boolean DEBUG = Log.isLoggable(TAG, Log.VERBOSE) || BuildConfig.DEBUG;
40 |
41 | public static int v(String tag, String msg) {
42 | return println(Log.VERBOSE, tag, msg);
43 | }
44 |
45 | public static int v(String tag, String msg, Throwable tr) {
46 | return println(Log.VERBOSE, tag, msg + '\n' + getStackTraceString(tr));
47 | }
48 |
49 | public static int d(String tag, String msg) {
50 | return println(Log.DEBUG, tag, msg);
51 | }
52 |
53 | public static int d(String tag, String msg, Throwable tr) {
54 | return println(Log.DEBUG, tag, msg + '\n' + getStackTraceString(tr));
55 | }
56 |
57 | public static int i(String tag, String msg) {
58 | return println(Log.INFO, tag, msg);
59 | }
60 |
61 | public static int i(String tag, String msg, Throwable tr) {
62 | return println(Log.INFO, tag, msg + '\n' + getStackTraceString(tr));
63 | }
64 |
65 | public static int w(String tag, String msg) {
66 | return println(Log.WARN, tag, msg);
67 | }
68 |
69 | public static int w(String tag, String msg, Throwable tr) {
70 | return println(Log.WARN, tag, msg + '\n' + getStackTraceString(tr));
71 | }
72 |
73 | public static int w(String tag, Throwable tr) {
74 | return println(Log.WARN, tag, getStackTraceString(tr));
75 | }
76 |
77 | public static int e(String tag, String msg) {
78 | return println(Log.ERROR, tag, msg);
79 | }
80 |
81 | public static int e(String tag, String msg, Throwable tr) {
82 | return println(Log.ERROR, tag, msg + '\n' + getStackTraceString(tr));
83 | }
84 |
85 | public static String getStackTraceString(Throwable tr) {
86 | return Log.getStackTraceString(tr);
87 | }
88 |
89 | public static int println(int priority, String tag, String msg) {
90 | if (priority > Log.INFO || DEBUG) {
91 | return Log.println(priority, tag, msg);
92 | } else {
93 | return 0;
94 | }
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/phone/src/mobi/espier/lgc/util/PreferencesUtil.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2010~2014 FMSoft (Espier Studio)
3 | *
4 | * This program is free software: you can redistribute it and/or modify it under the terms of the
5 | * GNU Affero General Public License as published by the Free Software Foundation, either version 3
6 | * of the License, or (at your option) any later version.
7 | *
8 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
9 | * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 | * Affero General Public License for more details.
11 | *
12 | * You should have received a copy of the GNU Affero General Public License along with this program.
13 | * If not, see .
14 | */
15 | package mobi.espier.lgc.util;
16 |
17 | import android.content.Context;
18 | import android.content.SharedPreferences;
19 | import android.preference.PreferenceManager;
20 |
21 | public class PreferencesUtil {
22 |
23 | public static boolean getBoolean(Context context, String key, boolean def) {
24 | SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
25 | return sp.getBoolean(key, def);
26 | }
27 |
28 | public static void putBoolean(Context context, String key, boolean value) {
29 | SharedPreferences.Editor editPrefs =
30 | PreferenceManager.getDefaultSharedPreferences(context).edit();
31 | editPrefs.putBoolean(key, value);
32 | editPrefs.commit();
33 | }
34 |
35 | public static String getString(Context context, String key, String def) {
36 | SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
37 | return sp.getString(key, def);
38 | }
39 |
40 | public static void putString(Context context, String key, String value) {
41 | SharedPreferences.Editor editPrefs =
42 | PreferenceManager.getDefaultSharedPreferences(context).edit();
43 | editPrefs.putString(key, value);
44 | editPrefs.commit();
45 | }
46 |
47 | public static Long getLong(Context context, String key, Long def) {
48 | SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
49 | return sp.getLong(key, def);
50 | }
51 |
52 | public static void putLong(Context context, String key, Long value) {
53 | SharedPreferences.Editor editPrefs =
54 | PreferenceManager.getDefaultSharedPreferences(context).edit();
55 | editPrefs.putLong(key, value);
56 | editPrefs.commit();
57 | }
58 |
59 | public static int getInt(Context context, String key, int def) {
60 | SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
61 | return sp.getInt(key, def);
62 | }
63 |
64 | public static void putInt(Context context, String key, int value) {
65 | SharedPreferences.Editor editPrefs =
66 | PreferenceManager.getDefaultSharedPreferences(context).edit();
67 | editPrefs.putInt(key, value);
68 | editPrefs.commit();
69 | }
70 |
71 | public static float getFloat(Context context, String key, float def) {
72 | SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
73 | return sp.getFloat(key, def);
74 | }
75 |
76 | public static void putFloat(Context context, String key, int value) {
77 | SharedPreferences.Editor editPrefs =
78 | PreferenceManager.getDefaultSharedPreferences(context).edit();
79 | editPrefs.putFloat(key, value);
80 | editPrefs.commit();
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/phone/src/mobi/espier/lgc/service/LgcAccessibilityService.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2010~2014 FMSoft (Espier Studio)
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Affero General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Affero General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Affero General Public License
15 | * along with this program. If not, see .
16 | *
17 | */
18 | package mobi.espier.lgc.service;
19 |
20 | import mobi.espier.lgc.LgcApp;
21 | import mobi.espier.lgc.util.LogUtils;
22 | import android.accessibilityservice.AccessibilityService;
23 | import android.accessibilityservice.AccessibilityServiceInfo;
24 | import android.app.Notification;
25 | import android.content.Intent;
26 | import android.os.Build;
27 | import android.view.accessibility.AccessibilityEvent;
28 |
29 | public class LgcAccessibilityService extends AccessibilityService {
30 | private static final String TAG = "WxLiveAccessibilibyService";
31 |
32 | private static boolean run = false;
33 | private static boolean enabled = true;
34 |
35 | public static boolean isRuning() {
36 | return run;
37 | }
38 |
39 | public static void setEnabled(boolean b) {
40 | enabled = b;
41 | }
42 |
43 | public LgcAccessibilityService() {}
44 |
45 | @Override
46 | public void onAccessibilityEvent(AccessibilityEvent event) {
47 | if (!enabled) {
48 | return;
49 | }
50 | if (AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED == event.getEventType()) {
51 | Notification notification = (Notification) event.getParcelableData();
52 | if (notification != null) {
53 | LogUtils.d(TAG, "receive notification from " + event.getPackageName()
54 | + "|title is " + notification.tickerText);
55 | LgcApp.getInstance().onNotification(event.getPackageName(), notification,
56 | System.currentTimeMillis());
57 | }
58 | } else if (AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED == event.getEventType()) {
59 | // find in android sources event.getPackageName() will not be null, but crash collect
60 | // show it is may be null
61 | CharSequence package_name = event.getPackageName();
62 | if (package_name != null) {
63 | LogUtils.d(TAG, "current package is : " + package_name);
64 | }
65 | }
66 | }
67 |
68 | @Override
69 | public void onInterrupt() {
70 | run = false;
71 | }
72 |
73 | @Override
74 | protected void onServiceConnected() {
75 | super.onServiceConnected();
76 | run = true;
77 | if (Build.VERSION.SDK_INT < 14) {
78 | AccessibilityServiceInfo serverInfo = new AccessibilityServiceInfo();
79 | serverInfo.eventTypes =
80 | AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED
81 | | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED;
82 | serverInfo.feedbackType = AccessibilityServiceInfo.FEEDBACK_VISUAL;
83 | serverInfo.flags = AccessibilityServiceInfo.DEFAULT;
84 | serverInfo.notificationTimeout = 0L;
85 | setServiceInfo(serverInfo);
86 | }
87 | }
88 |
89 | @Override
90 | public void onDestroy() {
91 | run = false;
92 | super.onDestroy();
93 | }
94 |
95 | @Override
96 | public void onRebind(Intent intent) {
97 | run = true;
98 | super.onRebind(intent);
99 | }
100 |
101 | @Override
102 | public boolean onUnbind(Intent intent) {
103 | run = false;
104 | return super.onUnbind(intent);
105 | }
106 |
107 | }
108 |
--------------------------------------------------------------------------------
/phone/res/layout/main.xml:
--------------------------------------------------------------------------------
1 |
2 |
21 |
26 |
32 |
37 |
43 |
44 |
45 |
46 |
52 |
60 |
61 |
67 |
73 |
74 |
80 |
87 |
88 |
94 |
101 |
108 |
109 |
110 |
117 |
118 |
119 |
--------------------------------------------------------------------------------
/phone/src/mobi/espier/lgc/LgcApp.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2010~2014 FMSoft (Espier Studio)
3 | *
4 | * This program is free software: you can redistribute it and/or modify it under the terms of the
5 | * GNU Affero General Public License as published by the Free Software Foundation, either version 3
6 | * of the License, or (at your option) any later version.
7 | *
8 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
9 | * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 | * Affero General Public License for more details.
11 | *
12 | * You should have received a copy of the GNU Affero General Public License along with this program.
13 | * If not, see .
14 | */
15 | package mobi.espier.lgc;
16 |
17 | import mobi.espier.lgc.data.LgcDataUtil;
18 | import mobi.espier.lgc.data.LgcProvider;
19 | import mobi.espier.lgc.data.MeteorHelper;
20 | import mobi.espier.lgc.util.LgcUtils;
21 | import mobi.espier.lgc.util.LogUtils;
22 | import mobi.espier.lgc.util.WeakHandlerTemplate;
23 | import android.app.Application;
24 | import android.app.Notification;
25 | import android.content.Intent;
26 | import android.os.Bundle;
27 | import android.os.Message;
28 | import android.os.Process;
29 | import android.support.v4.content.LocalBroadcastManager;
30 | import android.text.TextUtils;
31 |
32 | public class LgcApp extends Application {
33 | private static final int MSG_ON_NOTIFICATION = 10001;
34 | public static final String KEY_NOTIFICATION = "key_notification";
35 | public static final String KEY_NOTIFICATION_TIME = "key_notification_time";
36 | public static final String KEY_PACKAGE_NAME = "key_package_name";
37 |
38 | private WeakHandler mHandler = null;
39 | private static LgcApp sWxLiveApp = null;
40 |
41 | public static LgcApp getInstance() {
42 | return sWxLiveApp;
43 | }
44 |
45 | public LgcApp() {
46 | sWxLiveApp = this;
47 | LogUtils.i("xsm", "........................................ app.pid=" + Process.myPid());
48 | }
49 |
50 | @Override
51 | public void onCreate() {
52 | super.onCreate();
53 |
54 | mHandler = new WeakHandler(this);
55 | MeteorHelper.getInstance(this).connect();
56 | }
57 |
58 | public void onNotification(CharSequence packageName, Notification notification, long time) {
59 | Message message = mHandler.obtainMessage(MSG_ON_NOTIFICATION);
60 | Bundle data = new Bundle();
61 | data.putCharSequence(KEY_PACKAGE_NAME, packageName);
62 | data.putParcelable(KEY_NOTIFICATION, notification);
63 | data.putLong(KEY_NOTIFICATION_TIME, time);
64 | message.setData(data);
65 | mHandler.sendMessage(message);
66 | }
67 |
68 | public void saveNotification(Bundle data) {
69 | CharSequence packageName = data.getCharSequence(KEY_PACKAGE_NAME);
70 | if (!TextUtils.equals(packageName, "com.tencent.mm")) {
71 | return;
72 | }
73 |
74 | Notification notification = (Notification) data.getParcelable(KEY_NOTIFICATION);
75 | long time = data.getLong(KEY_NOTIFICATION_TIME);
76 | if (TextUtils.isEmpty(notification.tickerText)) {
77 | return;
78 | }
79 | // add code for save notification to db
80 | String title = notification.tickerText.toString();
81 | int index = title.indexOf(':');
82 |
83 | if (index > 0) {
84 | String name = title.substring(0, index).trim();
85 | int type = LgcProvider.DataColumns.TYPE_TEXT;
86 | String content = null;
87 | if (index < title.length()) {
88 | content = title.substring(index + 1).trim();
89 | }
90 |
91 | if (TextUtils.equals(content, "[图片]")) {
92 | type = LgcProvider.DataColumns.TYPE_IMAGE;
93 | } else if (TextUtils.equals(content, "[语音]")) {
94 | type = LgcProvider.DataColumns.TYPE_VOICE;
95 | }
96 | LgcDataUtil.saveNotification(this, name.trim(), content, type, time);
97 | LocalBroadcastManager.getInstance(this).sendBroadcast(
98 | new Intent(LgcUtils.ACTION_DATA_CHANGE));
99 | }
100 | }
101 |
102 | static class WeakHandler extends WeakHandlerTemplate {
103 |
104 | public WeakHandler(LgcApp context) {
105 | super(context);
106 | }
107 |
108 | @Override
109 | public void handleMessage(Message msg) {
110 | LgcApp app = getObject();
111 | switch (msg.what) {
112 | case MSG_ON_NOTIFICATION:
113 | app.saveNotification(msg.getData());
114 | break;
115 |
116 | default:
117 | }
118 | }
119 | };
120 | }
121 |
--------------------------------------------------------------------------------
/phone/src/mobi/espier/lgc/data/LgcDataUtil.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2010~2014 FMSoft (Espier Studio)
3 | *
4 | * This program is free software: you can redistribute it and/or modify it under the terms of the
5 | * GNU Affero General Public License as published by the Free Software Foundation, either version 3
6 | * of the License, or (at your option) any later version.
7 | *
8 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
9 | * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 | * Affero General Public License for more details.
11 | *
12 | * You should have received a copy of the GNU Affero General Public License along with this program.
13 | * If not, see .
14 | */
15 | package mobi.espier.lgc.data;
16 |
17 | import java.util.ArrayList;
18 | import java.util.List;
19 |
20 | import mobi.espier.lgc.util.SecurityUtils;
21 | import android.content.ContentValues;
22 | import android.content.Context;
23 | import android.database.Cursor;
24 | import android.net.Uri;
25 | import android.text.TextUtils;
26 |
27 | public class LgcDataUtil {
28 |
29 | public static Uri saveNotification(Context context, String name, String content, int type,
30 | long time) {
31 | if (content == null || TextUtils.isEmpty(name) || TextUtils.isEmpty(content)) {
32 | return null;
33 | }
34 |
35 | String hash = SecurityUtils.md5(name + content + time);
36 | ContentValues values = new ContentValues();
37 | values.put(LgcProvider.DataColumns.NAME, name);
38 | values.put(LgcProvider.DataColumns.CONTENT, content);
39 | values.put(LgcProvider.DataColumns.TYPE, type);
40 | values.put(LgcProvider.DataColumns.TIME, time);
41 | values.put(LgcProvider.DataColumns.HASH, hash);
42 | values.put(LgcProvider.DataColumns.SYNC, LgcProvider.DataColumns.SYNC_DEFAULT);
43 |
44 | return context.getContentResolver().insert(LgcProvider.NOTIFICATION_URI, values);
45 | }
46 |
47 | public static int markSyncDone(Context context, List ids) {
48 | if (ids == null || ids.size() < 1) {
49 | return 0;
50 | }
51 |
52 | ContentValues values = new ContentValues();
53 | values.put(LgcProvider.DataColumns.SYNC, LgcProvider.DataColumns.SYNC_DONE);
54 |
55 | StringBuilder sb = new StringBuilder();
56 | sb.append(" _id in (");
57 | int i = 0;
58 | for (String id : ids) {
59 | sb.append((i > 0) ? "," : "");
60 | sb.append(id);
61 | i++;
62 | }
63 | sb.append(" )");
64 |
65 | return context.getContentResolver().update(LgcProvider.NOTIFICATION_URI, values,
66 | sb.toString(), null);
67 | }
68 |
69 | public static int markSyncDone(Context context, long id) {
70 | if (id < 0) {
71 | return 0;
72 | }
73 |
74 | ContentValues values = new ContentValues();
75 | values.put(LgcProvider.DataColumns.SYNC, LgcProvider.DataColumns.SYNC_DONE);
76 |
77 | return context.getContentResolver().update(LgcProvider.NOTIFICATION_URI, values, "_id = ?",
78 | new String[] {Long.toString(id)});
79 | }
80 |
81 | public static int markAsSyncing(Context context, long id) {
82 | if (id < 0) {
83 | return 0;
84 | }
85 |
86 | ContentValues values = new ContentValues();
87 | values.put(LgcProvider.DataColumns.SYNC, LgcProvider.DataColumns.SYNC_ING);
88 |
89 | return context.getContentResolver().update(LgcProvider.NOTIFICATION_URI, values, "_id = ?",
90 | new String[] {Long.toString(id)});
91 | }
92 |
93 | public static class WxLiveNotification {
94 | public long id;
95 | public String name;
96 | public String content;
97 | public int type;
98 | public long time;
99 | public String hash;
100 | public int sync;
101 | }
102 |
103 | public static List queryNotification(Context context, int limit) {
104 | String order;
105 | if (limit > 0) {
106 | order = " _id asc limit " + limit;
107 | } else {
108 | order = " _ id asc";
109 | }
110 |
111 | Cursor cursor =
112 | context.getContentResolver().query(LgcProvider.NOTIFICATION_URI, null,
113 | LgcProvider.DataColumns.SYNC + " = ?", new String[] {"0"}, order);
114 | if (cursor == null) {
115 | return null;
116 | }
117 |
118 | ArrayList infos = new ArrayList();
119 | while (cursor.moveToNext()) {
120 | WxLiveNotification noti = new WxLiveNotification();
121 | noti.id = cursor.getLong(LgcProvider.DataColumns.INDEX_ID);
122 | noti.name = cursor.getString(LgcProvider.DataColumns.INDEX_NAME);
123 | noti.content = cursor.getString(LgcProvider.DataColumns.INDEX_CONTENT);
124 | noti.time = cursor.getLong(LgcProvider.DataColumns.INDEX_TIME);
125 | noti.type = cursor.getInt(LgcProvider.DataColumns.INDEX_TYPE);
126 | noti.hash = cursor.getString(LgcProvider.DataColumns.INDEX_HASH);
127 | noti.sync = cursor.getInt(LgcProvider.DataColumns.INDEX_SYNC);
128 | infos.add(noti);
129 | }
130 | cursor.close();
131 |
132 | return infos;
133 | }
134 |
135 | public static int clearData(Context context) {
136 | return context.getContentResolver().delete(LgcProvider.NOTIFICATION_URI, " sync = ? ",
137 | new String[] {"1"});
138 | }
139 |
140 | public static int getNoSyncCount(Context context) {
141 | Cursor cursor =
142 | context.getContentResolver().query(LgcProvider.NOTIFICATION_URI,
143 | new String[] {"count(*)"}, LgcProvider.DataColumns.SYNC + " = ?",
144 | new String[] {"0"}, null);
145 | if (cursor == null) {
146 | return 0;
147 | }
148 |
149 | int count = 0;
150 | if (cursor.moveToFirst()) {
151 | count = cursor.getInt(0);
152 | }
153 | cursor.close();
154 |
155 | return count;
156 | }
157 | }
158 |
--------------------------------------------------------------------------------
/phone/src/mobi/espier/lgc/data/UploadHelper.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2010~2014 FMSoft (Espier Studio)
3 | *
4 | * This program is free software: you can redistribute it and/or modify it under the terms of the
5 | * GNU Affero General Public License as published by the Free Software Foundation, either version 3
6 | * of the License, or (at your option) any later version.
7 | *
8 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
9 | * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 | * Affero General Public License for more details.
11 | *
12 | * You should have received a copy of the GNU Affero General Public License along with this program.
13 | * If not, see .
14 | */
15 | package mobi.espier.lgc.data;
16 |
17 | import java.io.BufferedReader;
18 | import java.io.InputStreamReader;
19 | import java.io.OutputStream;
20 | import java.net.HttpURLConnection;
21 | import java.net.SocketTimeoutException;
22 | import java.net.URL;
23 | import java.net.URLEncoder;
24 | import java.net.UnknownHostException;
25 | import java.util.ArrayList;
26 | import java.util.List;
27 |
28 | import mobi.espier.lgc.data.LgcDataUtil.WxLiveNotification;
29 | import mobi.espier.lgc.util.LgcUtils;
30 | import mobi.espier.lgc.util.LogUtils;
31 | import mobi.espier.lgc.util.SecurityUtils;
32 |
33 | import org.json.JSONArray;
34 | import org.json.JSONException;
35 | import org.json.JSONObject;
36 |
37 | import android.content.Context;
38 | import android.text.TextUtils;
39 |
40 | public class UploadHelper {
41 | private static final String TAG = "UploadHelper";
42 | private final Context mContext;
43 | private final String mUploadUrl;
44 | private List mIDList;
45 |
46 | public static String VERIFY_HEAD = "327aa";
47 | public static String VERIFY_TAIL = "738f6";
48 |
49 | public UploadHelper(Context context, String url) {
50 | mContext = context;
51 | mUploadUrl = url;
52 | }
53 |
54 | private String doHttpPostAndGetResponse(String url, byte[] data) {
55 | if (TextUtils.isEmpty(url) || data == null || data.length < 1) {
56 | return null;
57 | }
58 |
59 | String response = null;
60 | try {
61 | HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
62 | conn.setConnectTimeout(30000);
63 | conn.setReadTimeout(30000);
64 | conn.setRequestMethod("POST");
65 | conn.setDoOutput(true);
66 | conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
67 | conn.setRequestProperty("Content-Length", String.valueOf(data.length));
68 | OutputStream outStream = conn.getOutputStream();
69 | outStream.write(data);
70 |
71 | int mResponseCode = conn.getResponseCode();
72 | if (mResponseCode == 200) {
73 | response = getHttpResponse(conn);
74 | }
75 | conn.disconnect();
76 | } catch (UnknownHostException e) {
77 | e.printStackTrace();
78 | } catch (SocketTimeoutException e) {
79 | e.printStackTrace();
80 | } catch (Exception e) {
81 | e.printStackTrace();
82 | }
83 |
84 | return response;
85 | }
86 |
87 | private String getHttpResponse(HttpURLConnection conn) {
88 | String ret = "";
89 | try {
90 | BufferedReader reader =
91 | new BufferedReader(new InputStreamReader(conn.getInputStream()));
92 | String next = null;
93 | while ((next = reader.readLine()) != null) {
94 | ret += next;
95 | }
96 | } catch (Exception e) {
97 | e.printStackTrace();
98 | }
99 | return ret;
100 | }
101 |
102 | public String packageData(List notifications) {
103 | try {
104 | JSONArray array = new JSONArray();
105 | mIDList = new ArrayList();
106 | for (WxLiveNotification noti : notifications) {
107 | mIDList.add(Long.toString(noti.id));
108 | JSONObject stoneObject = new JSONObject();
109 | stoneObject.put("nickId", noti.name);
110 | stoneObject.put("content", noti.content);
111 | stoneObject.put("contentType", noti.type);
112 | stoneObject.put("createdAt", noti.time);
113 | stoneObject.put("hash", noti.hash);
114 | array.put(stoneObject);
115 | }
116 |
117 | String record = array.toString();
118 | StringBuilder sBuilder = new StringBuilder();
119 | sBuilder.append(VERIFY_HEAD).append(record).append(VERIFY_TAIL);
120 |
121 | StringBuilder sb = new StringBuilder();
122 | sb.append("chatRecords=").append(URLEncoder.encode(record)).append("&verify=")
123 | .append(SecurityUtils.md5(sBuilder.toString()));
124 | // return URLEncoder.encode(sb.toString());
125 | return sb.toString();
126 | } catch (JSONException e) {
127 | e.printStackTrace();
128 | }
129 | return null;
130 | }
131 |
132 | public void doUploadData() {
133 | doUploadData(LgcUtils.UPLOAD_LIMIT);
134 | }
135 |
136 | public void doUploadData(int limit) {
137 | List notis = LgcDataUtil.queryNotification(mContext, limit);
138 | LogUtils.d(TAG, ".................doUploadData query notification size = "
139 | + (notis != null ? notis.size() : 0));
140 |
141 | if (notis == null || notis.size() < 1) {
142 | return;
143 | }
144 |
145 | String data = packageData(notis);
146 | LogUtils.d(TAG, "................. doUploadData data = " + data);
147 | if (TextUtils.isEmpty(data)) {
148 | return;
149 | }
150 |
151 | LogUtils.d(TAG, "................. doUploadData url = " + mUploadUrl);
152 | String response = doHttpPostAndGetResponse(mUploadUrl, data.getBytes());
153 | LogUtils.d(TAG, "................. doUploadData response = " + response);
154 | LogUtils.d(TAG, "................. doUploadData mIDList = " + mIDList);
155 |
156 | if (TextUtils.equals("OK", response) && mIDList.size() > 0) {
157 | int count = LgcDataUtil.markSyncDone(mContext, mIDList);
158 | LogUtils.d(TAG, "................. doUploadData mark sync done = " + count);
159 | }
160 | }
161 | }
162 |
--------------------------------------------------------------------------------
/phone/src/mobi/espier/lgc/LgcActivity.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2010~2014 FMSoft (Espier Studio)
3 | *
4 | * This program is free software: you can redistribute it and/or modify it under the terms of the
5 | * GNU Affero General Public License as published by the Free Software Foundation, either version 3
6 | * of the License, or (at your option) any later version.
7 | *
8 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
9 | * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 | * Affero General Public License for more details.
11 | *
12 | * You should have received a copy of the GNU Affero General Public License along with this program.
13 | * If not, see .
14 | */
15 | package mobi.espier.lgc;
16 |
17 | import mobi.espier.lgc.data.MeteorHelper;
18 | import mobi.espier.lgc.service.LgcAccessibilityService;
19 | import mobi.espier.lgc.util.LgcUtils;
20 | import mobi.espier.lgc.util.LogUtils;
21 | import android.app.Activity;
22 | import android.content.BroadcastReceiver;
23 | import android.content.Context;
24 | import android.content.Intent;
25 | import android.content.IntentFilter;
26 | import android.os.Bundle;
27 | import android.provider.Settings;
28 | import android.support.v4.content.LocalBroadcastManager;
29 | import android.text.TextUtils;
30 | import android.view.View;
31 | import android.view.View.OnClickListener;
32 | import android.widget.Button;
33 | import android.widget.EditText;
34 | import android.widget.TextView;
35 | import android.widget.Toast;
36 |
37 | public class LgcActivity extends Activity {
38 | private static String TAG = "LgcActivity";
39 | private TextView mTvNotiServiceState;
40 | private Button mBtnAccessibility;
41 |
42 | private EditText mEdWebSocketUrl;
43 | private EditText mEdUsername;
44 | private EditText mEdPassword;
45 |
46 | private TextView mTvMeteorState;
47 |
48 | private Button mBtnStart;
49 | private Button mBtnStop;
50 |
51 | @Override
52 | public void onCreate(Bundle savedInstanceState) {
53 | super.onCreate(savedInstanceState);
54 | setContentView(R.layout.main);
55 |
56 | mTvNotiServiceState = (TextView) findViewById(R.id.lgc_tv_service_state);
57 | mBtnAccessibility = (Button) findViewById(R.id.lgc_btn_accessibility_setting);
58 | mBtnAccessibility.setOnClickListener(new OnClickListener() {
59 |
60 | @Override
61 | public void onClick(View v) {
62 | startAccessibilitySetting();
63 | }
64 |
65 | });
66 |
67 | mEdWebSocketUrl = (EditText) findViewById(R.id.lgc_edit_websocket_url);
68 | mEdUsername = (EditText) findViewById(R.id.lgc_edit_username);
69 | mEdPassword = (EditText) findViewById(R.id.lgc_edit_password);
70 |
71 | mBtnStart = (Button) findViewById(R.id.lgc_btn_start);
72 | mBtnStart.setOnClickListener(new OnClickListener() {
73 |
74 | @Override
75 | public void onClick(View v) {
76 | startMeteorSync();
77 | }
78 |
79 | });
80 | mBtnStop = (Button) findViewById(R.id.lgc_btn_stop);
81 | mBtnStop.setOnClickListener(new OnClickListener() {
82 |
83 | @Override
84 | public void onClick(View v) {
85 | stopMeteorSync();
86 | }
87 |
88 | });
89 |
90 | mTvMeteorState = (TextView) findViewById(R.id.tv_meteor_state);
91 |
92 | mEdWebSocketUrl.setText(LgcUtils.getWebsocketUrl(this, null));
93 | mEdUsername.setText(LgcUtils.getUsername(this));
94 | mEdPassword.setText(LgcUtils.getPasword(this));
95 |
96 | updateUIState();
97 |
98 | IntentFilter filter = new IntentFilter(LgcUtils.ACTION_METEOR_LOGIN_RESULT);
99 | filter.addAction(LgcUtils.ACTION_METEOR_STATE);
100 | LocalBroadcastManager.getInstance(this).registerReceiver(mReceiver, filter);
101 | }
102 |
103 | @Override
104 | protected void onResume() {
105 | super.onResume();
106 | boolean run = LgcAccessibilityService.isRuning();
107 | if (run) {
108 | mTvNotiServiceState.setText(getString(R.string.lgc_noti_service_running));
109 | } else {
110 | mTvNotiServiceState.setText(getString(R.string.lgc_noti_service_stop));
111 | }
112 | }
113 |
114 | @Override
115 | protected void onDestroy() {
116 | super.onDestroy();
117 | LocalBroadcastManager.getInstance(this).unregisterReceiver(mReceiver);
118 | }
119 |
120 | private void updateUIState() {
121 | if (MeteorHelper.getInstance(this).isConnected()) {
122 | mBtnStart.setEnabled(false);
123 | mBtnStop.setEnabled(true);
124 |
125 | mEdWebSocketUrl.setEnabled(false);
126 | mEdUsername.setEnabled(false);
127 | mEdPassword.setEnabled(false);
128 | } else {
129 | mBtnStart.setEnabled(true);
130 | mBtnStop.setEnabled(false);
131 |
132 | mEdWebSocketUrl.setEnabled(true);
133 | mEdUsername.setEnabled(true);
134 | mEdPassword.setEnabled(true);
135 | }
136 | }
137 |
138 | private void startAccessibilitySetting() {
139 | try {
140 | startActivity(new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS));
141 | } catch (Exception e) {
142 | startActivity(new Intent(Settings.ACTION_SETTINGS));
143 | e.printStackTrace();
144 | }
145 | }
146 |
147 |
148 | private void startMeteorSync() {
149 | String username = mEdUsername.getText().toString();
150 | String password = mEdPassword.getText().toString();
151 | String url = mEdWebSocketUrl.getText().toString();
152 |
153 | LgcUtils.setUsername(this, username);
154 | LgcUtils.setPasswrod(this, password);
155 | LgcUtils.setWebsocketUrl(this, url);
156 |
157 | if (TextUtils.isEmpty(url) || TextUtils.isEmpty(username) || TextUtils.isEmpty(password)) {
158 | String warning = getString(R.string.lgc_user_pw_url_empty_error);
159 | Toast.makeText(this, warning, Toast.LENGTH_LONG).show();
160 | updateState(warning);
161 | return;
162 | }
163 |
164 | MeteorHelper meteor = MeteorHelper.getInstance(this);
165 | meteor.connect(url, username, password);
166 | }
167 |
168 | private void stopMeteorSync() {
169 | MeteorHelper meteor = MeteorHelper.getInstance(this);
170 | meteor.disconnect();
171 |
172 | updateUIState();
173 | }
174 |
175 | private void updateState(String state) {
176 | mTvMeteorState.setText(state);
177 | }
178 |
179 | private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
180 |
181 | @Override
182 | public void onReceive(Context context, Intent intent) {
183 | String action = intent.getAction();
184 | if (TextUtils.equals(LgcUtils.ACTION_METEOR_LOGIN_RESULT, action)) {
185 | updateUIState();
186 | int event =
187 | intent.getIntExtra(LgcUtils.KEY_METEOR_LOGIN_RESULT,
188 | LgcUtils.METEOR_LOGIN_OK);
189 | if (LgcUtils.METEOR_LOGIN_FAILED == event) {
190 | String reason = intent.getStringExtra(LgcUtils.KEY_REASON);
191 | Toast.makeText(LgcActivity.this, getString(R.string.lgc_login_failed) + reason,
192 | Toast.LENGTH_LONG).show();
193 | }
194 | } else if (TextUtils.equals(LgcUtils.ACTION_METEOR_STATE, action)) {
195 | String state = intent.getStringExtra(LgcUtils.KEY_METEOR_STATE);
196 | LogUtils.d(TAG, "................... meteor state : " + state);
197 | updateState(state);
198 | }
199 | }
200 |
201 | };
202 | }
203 |
--------------------------------------------------------------------------------
/phone/src/mobi/espier/lgc/data/LgcProvider.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2010~2014 FMSoft (Espier Studio)
3 | *
4 | * This program is free software: you can redistribute it and/or modify it under the terms of the
5 | * GNU Affero General Public License as published by the Free Software Foundation, either version 3
6 | * of the License, or (at your option) any later version.
7 | *
8 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
9 | * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 | * Affero General Public License for more details.
11 | *
12 | * You should have received a copy of the GNU Affero General Public License along with this program.
13 | * If not, see .
14 | */
15 | package mobi.espier.lgc.data;
16 |
17 | import android.content.ContentProvider;
18 | import android.content.ContentUris;
19 | import android.content.ContentValues;
20 | import android.content.UriMatcher;
21 | import android.database.Cursor;
22 | import android.database.sqlite.SQLiteDatabase;
23 | import android.database.sqlite.SQLiteOpenHelper;
24 | import android.net.Uri;
25 | import android.provider.BaseColumns;
26 |
27 | public class LgcProvider extends ContentProvider {
28 | static final String AUTHORITY = "mobi.espier.lgc";
29 |
30 | private static final String[] TABLE_NAMES = new String[] {LgcDBHelper.TABLE_NAME};
31 |
32 | private static final int URI_MATCH_NOTIFICATION = 0;
33 | private static final int URI_MATCH_NOTIFICATION_ID = 10;
34 | public static final Uri NOTIFICATION_URI = Uri.parse("content://" + AUTHORITY + "/"
35 | + TABLE_NAMES[URI_MATCH_NOTIFICATION]);
36 |
37 | private static final UriMatcher URI_MATCHER;
38 | static {
39 | URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
40 | URI_MATCHER.addURI(AUTHORITY, TABLE_NAMES[URI_MATCH_NOTIFICATION], URI_MATCH_NOTIFICATION);
41 | URI_MATCHER.addURI(AUTHORITY, TABLE_NAMES[URI_MATCH_NOTIFICATION] + "/#",
42 | URI_MATCH_NOTIFICATION_ID);
43 | }
44 |
45 | private SQLiteOpenHelper mOpenHelper;
46 |
47 | @Override
48 | public boolean onCreate() {
49 | mOpenHelper = new LgcDBHelper(getContext());
50 | return true;
51 | }
52 |
53 | @Override
54 | public Cursor query(Uri uri, String[] projectionIn, String selection, String[] selectionArgs,
55 | String sortOrder) {
56 | int match = URI_MATCHER.match(uri);
57 | if (match == -1) {
58 | throw new IllegalArgumentException("Unknown URL");
59 | }
60 |
61 | SQLiteDatabase db = mOpenHelper.getReadableDatabase();
62 |
63 | String[] projection = null;
64 | if (projectionIn != null && projectionIn.length > 0) {
65 | projection = new String[projectionIn.length + 1];
66 | System.arraycopy(projectionIn, 0, projection, 0, projectionIn.length);
67 | projection[projectionIn.length] = "_id AS _id";
68 | }
69 |
70 | StringBuilder whereClause = new StringBuilder(256);
71 | if (match == URI_MATCH_NOTIFICATION_ID) {
72 | whereClause.append("(_id = ").append(uri.getPathSegments().get(1)).append(")");
73 | }
74 |
75 | if (selection != null && selection.length() > 0) {
76 | if (whereClause.length() > 0) {
77 | whereClause.append(" AND ");
78 | }
79 |
80 | whereClause.append('(');
81 | whereClause.append(selection);
82 | whereClause.append(')');
83 | }
84 |
85 | Cursor c =
86 | db.query(TABLE_NAMES[match % 10], projection, whereClause.toString(),
87 | selectionArgs, null, null, sortOrder, null);
88 | c.setNotificationUri(getContext().getContentResolver(), uri);
89 |
90 | return c;
91 | }
92 |
93 | @Override
94 | public String getType(Uri uri) {
95 | int match = URI_MATCHER.match(uri);
96 | switch (match) {
97 | case URI_MATCH_NOTIFICATION:
98 | return "vnd.android.cursor.dir/" + TABLE_NAMES[URI_MATCH_NOTIFICATION];
99 | case URI_MATCH_NOTIFICATION_ID:
100 | return "vnd.android.cursor.item/" + TABLE_NAMES[URI_MATCH_NOTIFICATION];
101 | default:
102 | throw new IllegalArgumentException("Unknown URL");
103 | }
104 | }
105 |
106 | @Override
107 | public Uri insert(Uri uri, ContentValues values) {
108 | SQLiteDatabase db = mOpenHelper.getWritableDatabase();
109 |
110 | int match = URI_MATCHER.match(uri);
111 | Uri retUri = null;
112 | switch (match) {
113 | case URI_MATCH_NOTIFICATION: {
114 | long rowID = db.insert(TABLE_NAMES[URI_MATCH_NOTIFICATION], "content", values);
115 | if (rowID > 0) {
116 | retUri = ContentUris.withAppendedId(NOTIFICATION_URI, rowID);
117 | }
118 | break;
119 | }
120 |
121 | default:
122 | throw new IllegalArgumentException("Unknown URL: " + uri);
123 | }
124 |
125 | if (retUri == null) {
126 | throw new IllegalArgumentException("Unknown URL: " + uri);
127 | }
128 | getContext().getContentResolver().notifyChange(retUri, null);
129 |
130 | return retUri;
131 | }
132 |
133 | @Override
134 | public int delete(Uri uri, String selection, String[] selectionArgs) {
135 | SQLiteDatabase db = mOpenHelper.getWritableDatabase();
136 |
137 | int match = URI_MATCHER.match(uri);
138 | if (match == -1) {
139 | throw new IllegalArgumentException("Unknown URL");
140 | }
141 |
142 | if (match == URI_MATCH_NOTIFICATION_ID) {
143 | StringBuilder sb = new StringBuilder();
144 | if (selection != null && selection.length() > 0) {
145 | sb.append("( ");
146 | sb.append(selection);
147 | sb.append(" ) AND ");
148 | }
149 | String id = uri.getPathSegments().get(1);
150 | sb.append("_id = ");
151 | sb.append(id);
152 | selection = sb.toString();
153 | }
154 |
155 | int count = db.delete(TABLE_NAMES[match % 10], selection, selectionArgs);
156 | getContext().getContentResolver().notifyChange(uri, null);
157 | return count;
158 | }
159 |
160 | @Override
161 | public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
162 | SQLiteDatabase db = mOpenHelper.getWritableDatabase();
163 |
164 | int match = URI_MATCHER.match(uri);
165 | if (match == -1) {
166 | throw new IllegalArgumentException("Unknown URL");
167 | }
168 |
169 | if (match == URI_MATCH_NOTIFICATION_ID) {
170 | StringBuilder sb = new StringBuilder();
171 | if (selection != null && selection.length() > 0) {
172 | sb.append("( ");
173 | sb.append(selection);
174 | sb.append(" ) AND ");
175 | }
176 | String id = uri.getPathSegments().get(1);
177 | sb.append("_id = ");
178 | sb.append(id);
179 | selection = sb.toString();
180 | }
181 |
182 | int ret = db.update(TABLE_NAMES[match % 10], values, selection, selectionArgs);
183 | getContext().getContentResolver().notifyChange(uri, null);
184 | return ret;
185 | }
186 |
187 | public class DataColumns implements BaseColumns {
188 | public static final String NAME = "name";
189 | public static final String CONTENT = "content";
190 | public static final String TYPE = "type";
191 | public static final String TIME = "time";
192 | public static final String HASH = "hash";
193 | public static final String SYNC = "sync";
194 |
195 | public static final int INDEX_ID = 0;
196 | public static final int INDEX_NAME = 1;
197 | public static final int INDEX_CONTENT = 2;
198 | public static final int INDEX_TYPE = 3;
199 | public static final int INDEX_TIME = 4;
200 | public static final int INDEX_HASH = 5;
201 | public static final int INDEX_SYNC = 6;
202 |
203 | public static final int TYPE_TEXT = 1;
204 | public static final int TYPE_VOICE = 2;
205 | public static final int TYPE_IMAGE = 3;
206 |
207 | public static final int SYNC_DEFAULT = 0;
208 | public static final int SYNC_DONE = 1;
209 | public static final int SYNC_ING = 2;
210 | }
211 | }
212 |
--------------------------------------------------------------------------------
/phone/src/mobi/espier/lgc/data/MeteorHelper.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2010~2014 FMSoft (Espier Studio)
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Affero General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Affero General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Affero General Public License
15 | * along with this program. If not, see .
16 | *
17 | */
18 | package mobi.espier.lgc.data;
19 |
20 | import im.delight.android.ddp.Meteor;
21 | import im.delight.android.ddp.MeteorCallback;
22 | import im.delight.android.ddp.ResultListener;
23 |
24 | import java.util.HashMap;
25 | import java.util.List;
26 | import java.util.Map;
27 |
28 | import mobi.espier.lgc.R;
29 | import mobi.espier.lgc.data.LgcDataUtil.WxLiveNotification;
30 | import mobi.espier.lgc.util.LgcUtils;
31 | import mobi.espier.lgc.util.LogUtils;
32 | import android.content.BroadcastReceiver;
33 | import android.content.Context;
34 | import android.content.Intent;
35 | import android.content.IntentFilter;
36 | import android.support.v4.content.LocalBroadcastManager;
37 | import android.text.TextUtils;
38 | import android.widget.Toast;
39 |
40 | public class MeteorHelper implements MeteorCallback {
41 | private static final String TAG = "meteor";
42 | private final Context mContext;
43 | private Meteor mMeteor = null;
44 | private String mUrl;
45 | private String mUsername;
46 | private String mPassword;
47 |
48 | private final boolean mEnableUserAuth = true;
49 |
50 | private static MeteorHelper sMeteorHelper = null;
51 |
52 | public static MeteorHelper getInstance(Context context) {
53 | if (sMeteorHelper == null) {
54 | sMeteorHelper = new MeteorHelper(context);
55 | }
56 | return sMeteorHelper;
57 | }
58 |
59 | public MeteorHelper(Context context) {
60 | mContext = context;
61 |
62 | IntentFilter filter = new IntentFilter(LgcUtils.ACTION_DATA_CHANGE);
63 | filter.addAction(LgcUtils.ACTION_METEOR_LOGIN_RESULT);
64 | LocalBroadcastManager.getInstance(mContext).registerReceiver(mReceiver, filter);
65 | }
66 |
67 | public void connect() {
68 | String url = LgcUtils.getWebsocketUrl(mContext, null);
69 | String username = LgcUtils.getUsername(mContext);
70 | String password = LgcUtils.getPasword(mContext);
71 | connect(url, username, password);
72 | }
73 |
74 | public void connect(String url, String username, String password) {
75 | if (TextUtils.isEmpty(url) || TextUtils.isEmpty(username) || TextUtils.isEmpty(password)) {
76 | String warning = mContext.getString(R.string.lgc_user_pw_url_empty_error);
77 | Toast.makeText(mContext, warning, Toast.LENGTH_LONG).show();
78 | sendMeteorState(warning);
79 | LogUtils.d(TAG, "connect|url=" + url + "|user=" + username + "|password=" + password
80 | + "|do nothing............................");
81 | return;
82 | }
83 |
84 | if (TextUtils.equals(url, mUrl) && TextUtils.equals(username, mUsername)
85 | && TextUtils.equals(password, mPassword) && mMeteor != null
86 | && mMeteor.isConnected()) {
87 | return;
88 | }
89 | disconnect();
90 |
91 | LogUtils.d(TAG, "connect|url=" + url + "|user=" + username + "|password=" + password);
92 | mUrl = url;
93 | mUsername = username;
94 | mPassword = password;
95 |
96 | sendMeteorState(mContext.getString(R.string.lgc_meteor_state_connect));
97 |
98 | mMeteor = new Meteor(mUrl);
99 | mMeteor.setCallback(this);
100 | }
101 |
102 | public void disconnect() {
103 | LogUtils.d(TAG, "disconnect");
104 | sendMeteorState("");
105 | if (mMeteor != null) {
106 | mMeteor.disconnect();
107 | }
108 | mMeteor = null;
109 | }
110 |
111 | public boolean isConnected() {
112 | LogUtils.d(TAG, "isConnected");
113 | if (mMeteor != null) {
114 | return mMeteor.isConnected();
115 | }
116 | return false;
117 | }
118 |
119 | @Override
120 | public void onConnect() {
121 | LogUtils.d(TAG, "onConnect");
122 | sendMeteorState(mContext.getString(R.string.lgc_meteor_state_connect_ok));
123 | if (!mEnableUserAuth) {
124 | return;
125 | }
126 |
127 | sendMeteorState(mContext.getString(R.string.lgc_meteor_state_user_login));
128 | // do user auth
129 | mMeteor.loginWithUsername(mUsername, mPassword, new ResultListener() {
130 |
131 | @Override
132 | public void onSuccess(String result) {
133 | LogUtils.i(TAG, "................................. login success : " + result);
134 | Intent intent = new Intent(LgcUtils.ACTION_METEOR_LOGIN_RESULT);
135 | intent.putExtra(LgcUtils.KEY_METEOR_LOGIN_RESULT, LgcUtils.METEOR_LOGIN_OK);
136 | LocalBroadcastManager.getInstance(mContext).sendBroadcast(intent);
137 | sendMeteorState(mContext.getString(R.string.lgc_meteor_state_user_login_ok));
138 | }
139 |
140 | @Override
141 | public void onError(String error, String reason, String details) {
142 | LogUtils.i(TAG, "................................. login failed error=" + error
143 | + "|reason=" + reason + "|details=" + details);
144 |
145 | Intent intent = new Intent(LgcUtils.ACTION_METEOR_LOGIN_RESULT);
146 | intent.putExtra(LgcUtils.KEY_METEOR_LOGIN_RESULT,
147 | LgcUtils.METEOR_LOGIN_FAILED);
148 | intent.putExtra(LgcUtils.KEY_REASON, reason);
149 |
150 | LocalBroadcastManager.getInstance(mContext).sendBroadcast(intent);
151 | disconnect();
152 | sendMeteorState(mContext.getString(R.string.lgc_meteor_state_user_login_failed));
153 | }
154 |
155 | });
156 | }
157 |
158 | @Override
159 | public void onDisconnect(int code, String reason) {
160 | LogUtils.d(TAG, "onDisconnect|code=" + code + "|reason=" + reason);
161 | sendMeteorState(mContext.getString(R.string.lgc_meteor_state_disconnect_reason) + reason);
162 | connect(mUrl, mUsername, mPassword);
163 | }
164 |
165 | @Override
166 | public void onDataAdded(String collectionName, String documentID, String fieldsJson) {
167 | LogUtils.d(TAG, "onDataAdded|collectionName=" + collectionName + "|documentID="
168 | + documentID + "|fieldsJson=" + fieldsJson);
169 | }
170 |
171 | @Override
172 | public void onDataChanged(String collectionName, String documentID, String updatedValuesJson,
173 | String removedValuesJson) {
174 | LogUtils.d(TAG, "onDataChanged|collectionName=" + collectionName + "|documentID="
175 | + documentID + "|updatedValuesJson=" + removedValuesJson);
176 | }
177 |
178 | @Override
179 | public void onDataRemoved(String collectionName, String documentID) {
180 | LogUtils.d(TAG, "onDataRemoved|collectionName=" + collectionName + "|documentID="
181 | + documentID);
182 | }
183 |
184 | @Override
185 | public void onException(Exception e) {
186 | if (e != null) {
187 | LogUtils.d(TAG, "onException|e=" + e.toString(), e);
188 | }
189 | }
190 |
191 | public void sendMeteorState(String state) {
192 | Intent intent = new Intent(LgcUtils.ACTION_METEOR_STATE);
193 | intent.putExtra(LgcUtils.KEY_METEOR_STATE, state);
194 |
195 | LocalBroadcastManager.getInstance(mContext).sendBroadcast(intent);
196 | }
197 |
198 | public void sendData(String nickId, String content, int contentType, long createAt,
199 | String hash, InsertListener listener) {
200 | sendMeteorState(mContext.getString(R.string.lgc_meteor_state_update_data));
201 | Map data = new HashMap();
202 | data.put("nickId", nickId);
203 | data.put("content", content);
204 | data.put("contentType", contentType);
205 | data.put("createdAt", createAt);
206 | data.put("hash", hash);
207 | mMeteor.insert("wx_chat_records", data, listener);
208 |
209 | }
210 |
211 | public void doUploadData() {
212 | doUploadData(LgcUtils.UPLOAD_LIMIT);
213 | }
214 |
215 | public void doUploadData(int limit) {
216 | if (mMeteor == null || !mMeteor.isConnected()) {
217 | return;
218 | }
219 |
220 | List notis = LgcDataUtil.queryNotification(mContext, limit);
221 | LogUtils.d(TAG, ".................doUploadData query notification size = "
222 | + (notis != null ? notis.size() : 0));
223 |
224 | if (notis == null || notis.size() < 1) {
225 | return;
226 | }
227 |
228 | for (WxLiveNotification noti : notis) {
229 | sendData(noti.name, noti.content, noti.type, noti.time, noti.hash, new InsertListener(
230 | mContext, noti.id));
231 | LgcDataUtil.markAsSyncing(mContext, noti.id);
232 | LogUtils.d(TAG, ".................doUploadData mark as ing = " + noti.id);
233 | }
234 | }
235 |
236 | private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
237 |
238 | @Override
239 | public void onReceive(Context context, Intent intent) {
240 | String action = intent.getAction();
241 | if (TextUtils.equals(LgcUtils.ACTION_METEOR_LOGIN_RESULT, action)) {
242 | int event =
243 | intent.getIntExtra(LgcUtils.KEY_METEOR_LOGIN_RESULT,
244 | LgcUtils.METEOR_LOGIN_OK);
245 | if (LgcUtils.METEOR_LOGIN_OK == event) {
246 | LogUtils.d(TAG,
247 | "........................................ login ok.........................");
248 | doUploadData();
249 | }
250 | } else if (TextUtils.equals(LgcUtils.ACTION_DATA_CHANGE, action)) {
251 | doUploadData();
252 | }
253 | }
254 |
255 | };
256 |
257 | private static class InsertListener implements ResultListener {
258 | private final long dbId;
259 | private final Context context;
260 |
261 | public InsertListener(Context context, long dbId) {
262 | this.dbId = dbId;
263 | this.context = context;
264 | }
265 |
266 | @Override
267 | public void onSuccess(String result) {
268 | LogUtils.i(TAG, ".........................................onSuccess=" + result);
269 | LgcDataUtil.markSyncDone(this.context, dbId);
270 | MeteorHelper.getInstance(context).sendMeteorState("");
271 | }
272 |
273 | @Override
274 | public void onError(String error, String reason, String details) {
275 | LogUtils.i(TAG, ".........................................error ...error=" + error
276 | + "|reason=" + reason + "|details=" + details);
277 | }
278 |
279 | };
280 | }
281 |
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/css/bootstrap-datepicker.min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Datepicker for Bootstrap v1.4.0 (https://github.com/eternicode/bootstrap-datepicker)
3 | *
4 | * Copyright 2012 Stefan Petre
5 | * Improvements by Andrew Rowls
6 | * Licensed under the Apache License v2.0 (http://www.apache.org/licenses/LICENSE-2.0)
7 | */
8 | .datepicker{padding:4px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;direction:ltr}.datepicker-inline{width:220px}.datepicker.datepicker-rtl{direction:rtl}.datepicker.datepicker-rtl table tr td span{float:right}.datepicker-dropdown{top:0;left:0}.datepicker-dropdown:before{content:'';display:inline-block;border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-top:0;border-bottom-color:rgba(0,0,0,.2);position:absolute}.datepicker-dropdown:after{content:'';display:inline-block;border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #fff;border-top:0;position:absolute}.datepicker-dropdown.datepicker-orient-left:before{left:6px}.datepicker-dropdown.datepicker-orient-left:after{left:7px}.datepicker-dropdown.datepicker-orient-right:before{right:6px}.datepicker-dropdown.datepicker-orient-right:after{right:7px}.datepicker-dropdown.datepicker-orient-top:before{top:-7px}.datepicker-dropdown.datepicker-orient-top:after{top:-6px}.datepicker-dropdown.datepicker-orient-bottom:before{bottom:-7px;border-bottom:0;border-top:7px solid #999}.datepicker-dropdown.datepicker-orient-bottom:after{bottom:-6px;border-bottom:0;border-top:6px solid #fff}.datepicker>div{display:none}.datepicker.days .datepicker-days,.datepicker.months .datepicker-months,.datepicker.years .datepicker-years{display:block}.datepicker table{margin:0;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.datepicker td,.datepicker th{text-align:center;width:20px;height:20px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;border:none}.table-striped .datepicker table tr td,.table-striped .datepicker table tr th{background-color:transparent}.datepicker table tr td.day:hover,.datepicker table tr td.day.focused{background:#eee;cursor:pointer}.datepicker table tr td.old,.datepicker table tr td.new{color:#999}.datepicker table tr td.disabled,.datepicker table tr td.disabled:hover{background:0 0;color:#999;cursor:default}.datepicker table tr td.today,.datepicker table tr td.today:hover,.datepicker table tr td.today.disabled,.datepicker table tr td.today.disabled:hover{background-color:#fde19a;background-image:-moz-linear-gradient(top,#fdd49a,#fdf59a);background-image:-ms-linear-gradient(top,#fdd49a,#fdf59a);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fdd49a),to(#fdf59a));background-image:-webkit-linear-gradient(top,#fdd49a,#fdf59a);background-image:-o-linear-gradient(top,#fdd49a,#fdf59a);background-image:linear-gradient(top,#fdd49a,#fdf59a);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fdd49a', endColorstr='#fdf59a', GradientType=0);border-color:#fdf59a #fdf59a #fbed50;border-color:rgba(0,0,0,.1) rgba(0,0,0,.1) rgba(0,0,0,.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);color:#000}.datepicker table tr td.today:hover,.datepicker table tr td.today:hover:hover,.datepicker table tr td.today.disabled:hover,.datepicker table tr td.today.disabled:hover:hover,.datepicker table tr td.today:active,.datepicker table tr td.today:hover:active,.datepicker table tr td.today.disabled:active,.datepicker table tr td.today.disabled:hover:active,.datepicker table tr td.today.active,.datepicker table tr td.today:hover.active,.datepicker table tr td.today.disabled.active,.datepicker table tr td.today.disabled:hover.active,.datepicker table tr td.today.disabled,.datepicker table tr td.today:hover.disabled,.datepicker table tr td.today.disabled.disabled,.datepicker table tr td.today.disabled:hover.disabled,.datepicker table tr td.today[disabled],.datepicker table tr td.today:hover[disabled],.datepicker table tr td.today.disabled[disabled],.datepicker table tr td.today.disabled:hover[disabled]{background-color:#fdf59a}.datepicker table tr td.today:active,.datepicker table tr td.today:hover:active,.datepicker table tr td.today.disabled:active,.datepicker table tr td.today.disabled:hover:active,.datepicker table tr td.today.active,.datepicker table tr td.today:hover.active,.datepicker table tr td.today.disabled.active,.datepicker table tr td.today.disabled:hover.active{background-color:#fbf069 \9}.datepicker table tr td.today:hover:hover{color:#000}.datepicker table tr td.today.active:hover{color:#fff}.datepicker table tr td.range,.datepicker table tr td.range:hover,.datepicker table tr td.range.disabled,.datepicker table tr td.range.disabled:hover{background:#eee;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.datepicker table tr td.range.today,.datepicker table tr td.range.today:hover,.datepicker table tr td.range.today.disabled,.datepicker table tr td.range.today.disabled:hover{background-color:#f3d17a;background-image:-moz-linear-gradient(top,#f3c17a,#f3e97a);background-image:-ms-linear-gradient(top,#f3c17a,#f3e97a);background-image:-webkit-gradient(linear,0 0,0 100%,from(#f3c17a),to(#f3e97a));background-image:-webkit-linear-gradient(top,#f3c17a,#f3e97a);background-image:-o-linear-gradient(top,#f3c17a,#f3e97a);background-image:linear-gradient(top,#f3c17a,#f3e97a);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#f3c17a', endColorstr='#f3e97a', GradientType=0);border-color:#f3e97a #f3e97a #edde34;border-color:rgba(0,0,0,.1) rgba(0,0,0,.1) rgba(0,0,0,.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.datepicker table tr td.range.today:hover,.datepicker table tr td.range.today:hover:hover,.datepicker table tr td.range.today.disabled:hover,.datepicker table tr td.range.today.disabled:hover:hover,.datepicker table tr td.range.today:active,.datepicker table tr td.range.today:hover:active,.datepicker table tr td.range.today.disabled:active,.datepicker table tr td.range.today.disabled:hover:active,.datepicker table tr td.range.today.active,.datepicker table tr td.range.today:hover.active,.datepicker table tr td.range.today.disabled.active,.datepicker table tr td.range.today.disabled:hover.active,.datepicker table tr td.range.today.disabled,.datepicker table tr td.range.today:hover.disabled,.datepicker table tr td.range.today.disabled.disabled,.datepicker table tr td.range.today.disabled:hover.disabled,.datepicker table tr td.range.today[disabled],.datepicker table tr td.range.today:hover[disabled],.datepicker table tr td.range.today.disabled[disabled],.datepicker table tr td.range.today.disabled:hover[disabled]{background-color:#f3e97a}.datepicker table tr td.range.today:active,.datepicker table tr td.range.today:hover:active,.datepicker table tr td.range.today.disabled:active,.datepicker table tr td.range.today.disabled:hover:active,.datepicker table tr td.range.today.active,.datepicker table tr td.range.today:hover.active,.datepicker table tr td.range.today.disabled.active,.datepicker table tr td.range.today.disabled:hover.active{background-color:#efe24b \9}.datepicker table tr td.selected,.datepicker table tr td.selected:hover,.datepicker table tr td.selected.disabled,.datepicker table tr td.selected.disabled:hover{background-color:#9e9e9e;background-image:-moz-linear-gradient(top,#b3b3b3,gray);background-image:-ms-linear-gradient(top,#b3b3b3,gray);background-image:-webkit-gradient(linear,0 0,0 100%,from(#b3b3b3),to(gray));background-image:-webkit-linear-gradient(top,#b3b3b3,gray);background-image:-o-linear-gradient(top,#b3b3b3,gray);background-image:linear-gradient(top,#b3b3b3,gray);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#b3b3b3', endColorstr='#808080', GradientType=0);border-color:gray #808080 #595959;border-color:rgba(0,0,0,.1) rgba(0,0,0,.1) rgba(0,0,0,.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,.25)}.datepicker table tr td.selected:hover,.datepicker table tr td.selected:hover:hover,.datepicker table tr td.selected.disabled:hover,.datepicker table tr td.selected.disabled:hover:hover,.datepicker table tr td.selected:active,.datepicker table tr td.selected:hover:active,.datepicker table tr td.selected.disabled:active,.datepicker table tr td.selected.disabled:hover:active,.datepicker table tr td.selected.active,.datepicker table tr td.selected:hover.active,.datepicker table tr td.selected.disabled.active,.datepicker table tr td.selected.disabled:hover.active,.datepicker table tr td.selected.disabled,.datepicker table tr td.selected:hover.disabled,.datepicker table tr td.selected.disabled.disabled,.datepicker table tr td.selected.disabled:hover.disabled,.datepicker table tr td.selected[disabled],.datepicker table tr td.selected:hover[disabled],.datepicker table tr td.selected.disabled[disabled],.datepicker table tr td.selected.disabled:hover[disabled]{background-color:gray}.datepicker table tr td.selected:active,.datepicker table tr td.selected:hover:active,.datepicker table tr td.selected.disabled:active,.datepicker table tr td.selected.disabled:hover:active,.datepicker table tr td.selected.active,.datepicker table tr td.selected:hover.active,.datepicker table tr td.selected.disabled.active,.datepicker table tr td.selected.disabled:hover.active{background-color:#666 \9}.datepicker table tr td.active,.datepicker table tr td.active:hover,.datepicker table tr td.active.disabled,.datepicker table tr td.active.disabled:hover{background-color:#006dcc;background-image:-moz-linear-gradient(top,#08c,#04c);background-image:-ms-linear-gradient(top,#08c,#04c);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#04c));background-image:-webkit-linear-gradient(top,#08c,#04c);background-image:-o-linear-gradient(top,#08c,#04c);background-image:linear-gradient(top,#08c,#04c);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);border-color:#04c #04c #002a80;border-color:rgba(0,0,0,.1) rgba(0,0,0,.1) rgba(0,0,0,.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,.25)}.datepicker table tr td.active:hover,.datepicker table tr td.active:hover:hover,.datepicker table tr td.active.disabled:hover,.datepicker table tr td.active.disabled:hover:hover,.datepicker table tr td.active:active,.datepicker table tr td.active:hover:active,.datepicker table tr td.active.disabled:active,.datepicker table tr td.active.disabled:hover:active,.datepicker table tr td.active.active,.datepicker table tr td.active:hover.active,.datepicker table tr td.active.disabled.active,.datepicker table tr td.active.disabled:hover.active,.datepicker table tr td.active.disabled,.datepicker table tr td.active:hover.disabled,.datepicker table tr td.active.disabled.disabled,.datepicker table tr td.active.disabled:hover.disabled,.datepicker table tr td.active[disabled],.datepicker table tr td.active:hover[disabled],.datepicker table tr td.active.disabled[disabled],.datepicker table tr td.active.disabled:hover[disabled]{background-color:#04c}.datepicker table tr td.active:active,.datepicker table tr td.active:hover:active,.datepicker table tr td.active.disabled:active,.datepicker table tr td.active.disabled:hover:active,.datepicker table tr td.active.active,.datepicker table tr td.active:hover.active,.datepicker table tr td.active.disabled.active,.datepicker table tr td.active.disabled:hover.active{background-color:#039 \9}.datepicker table tr td span{display:block;width:23%;height:54px;line-height:54px;float:left;margin:1%;cursor:pointer;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.datepicker table tr td span:hover{background:#eee}.datepicker table tr td span.disabled,.datepicker table tr td span.disabled:hover{background:0 0;color:#999;cursor:default}.datepicker table tr td span.active,.datepicker table tr td span.active:hover,.datepicker table tr td span.active.disabled,.datepicker table tr td span.active.disabled:hover{background-color:#006dcc;background-image:-moz-linear-gradient(top,#08c,#04c);background-image:-ms-linear-gradient(top,#08c,#04c);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#04c));background-image:-webkit-linear-gradient(top,#08c,#04c);background-image:-o-linear-gradient(top,#08c,#04c);background-image:linear-gradient(top,#08c,#04c);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);border-color:#04c #04c #002a80;border-color:rgba(0,0,0,.1) rgba(0,0,0,.1) rgba(0,0,0,.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,.25)}.datepicker table tr td span.active:hover,.datepicker table tr td span.active:hover:hover,.datepicker table tr td span.active.disabled:hover,.datepicker table tr td span.active.disabled:hover:hover,.datepicker table tr td span.active:active,.datepicker table tr td span.active:hover:active,.datepicker table tr td span.active.disabled:active,.datepicker table tr td span.active.disabled:hover:active,.datepicker table tr td span.active.active,.datepicker table tr td span.active:hover.active,.datepicker table tr td span.active.disabled.active,.datepicker table tr td span.active.disabled:hover.active,.datepicker table tr td span.active.disabled,.datepicker table tr td span.active:hover.disabled,.datepicker table tr td span.active.disabled.disabled,.datepicker table tr td span.active.disabled:hover.disabled,.datepicker table tr td span.active[disabled],.datepicker table tr td span.active:hover[disabled],.datepicker table tr td span.active.disabled[disabled],.datepicker table tr td span.active.disabled:hover[disabled]{background-color:#04c}.datepicker table tr td span.active:active,.datepicker table tr td span.active:hover:active,.datepicker table tr td span.active.disabled:active,.datepicker table tr td span.active.disabled:hover:active,.datepicker table tr td span.active.active,.datepicker table tr td span.active:hover.active,.datepicker table tr td span.active.disabled.active,.datepicker table tr td span.active.disabled:hover.active{background-color:#039 \9}.datepicker table tr td span.old,.datepicker table tr td span.new{color:#999}.datepicker .datepicker-switch{width:145px}.datepicker thead tr:first-child th,.datepicker tfoot tr th{cursor:pointer}.datepicker thead tr:first-child th:hover,.datepicker tfoot tr th:hover{background:#eee}.datepicker .cw{font-size:10px;width:12px;padding:0 2px 0 5px;vertical-align:middle}.datepicker thead tr:first-child .cw{cursor:default;background-color:transparent}.input-append.date .add-on,.input-prepend.date .add-on{cursor:pointer}.input-append.date .add-on i,.input-prepend.date .add-on i{margin-top:3px}.input-daterange input{text-align:center}.input-daterange input:first-child{-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px}.input-daterange input:last-child{-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0}.input-daterange .add-on{display:inline-block;width:auto;min-width:16px;height:18px;padding:4px 5px;font-weight:400;line-height:18px;text-align:center;text-shadow:0 1px 0 #fff;vertical-align:middle;background-color:#eee;border:1px solid #ccc;margin-left:-5px;margin-right:-5px}
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/css/bootstrap-datepicker.standalone.min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Datepicker for Bootstrap v1.4.0 (https://github.com/eternicode/bootstrap-datepicker)
3 | *
4 | * Copyright 2012 Stefan Petre
5 | * Improvements by Andrew Rowls
6 | * Licensed under the Apache License v2.0 (http://www.apache.org/licenses/LICENSE-2.0)
7 | */
8 | .datepicker{padding:4px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;direction:ltr}.datepicker-inline{width:220px}.datepicker.datepicker-rtl{direction:rtl}.datepicker.datepicker-rtl table tr td span{float:right}.datepicker-dropdown{top:0;left:0}.datepicker-dropdown:before{content:'';display:inline-block;border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-top:0;border-bottom-color:rgba(0,0,0,.2);position:absolute}.datepicker-dropdown:after{content:'';display:inline-block;border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #fff;border-top:0;position:absolute}.datepicker-dropdown.datepicker-orient-left:before{left:6px}.datepicker-dropdown.datepicker-orient-left:after{left:7px}.datepicker-dropdown.datepicker-orient-right:before{right:6px}.datepicker-dropdown.datepicker-orient-right:after{right:7px}.datepicker-dropdown.datepicker-orient-top:before{top:-7px}.datepicker-dropdown.datepicker-orient-top:after{top:-6px}.datepicker-dropdown.datepicker-orient-bottom:before{bottom:-7px;border-bottom:0;border-top:7px solid #999}.datepicker-dropdown.datepicker-orient-bottom:after{bottom:-6px;border-bottom:0;border-top:6px solid #fff}.datepicker>div{display:none}.datepicker.days .datepicker-days,.datepicker.months .datepicker-months,.datepicker.years .datepicker-years{display:block}.datepicker table{margin:0;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.datepicker td,.datepicker th{text-align:center;width:20px;height:20px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;border:none}.table-striped .datepicker table tr td,.table-striped .datepicker table tr th{background-color:transparent}.datepicker table tr td.day:hover,.datepicker table tr td.day.focused{background:#eee;cursor:pointer}.datepicker table tr td.old,.datepicker table tr td.new{color:#999}.datepicker table tr td.disabled,.datepicker table tr td.disabled:hover{background:0 0;color:#999;cursor:default}.datepicker table tr td.today,.datepicker table tr td.today:hover,.datepicker table tr td.today.disabled,.datepicker table tr td.today.disabled:hover{background-color:#fde19a;background-image:-moz-linear-gradient(top,#fdd49a,#fdf59a);background-image:-ms-linear-gradient(top,#fdd49a,#fdf59a);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fdd49a),to(#fdf59a));background-image:-webkit-linear-gradient(top,#fdd49a,#fdf59a);background-image:-o-linear-gradient(top,#fdd49a,#fdf59a);background-image:linear-gradient(top,#fdd49a,#fdf59a);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fdd49a', endColorstr='#fdf59a', GradientType=0);border-color:#fdf59a #fdf59a #fbed50;border-color:rgba(0,0,0,.1) rgba(0,0,0,.1) rgba(0,0,0,.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);color:#000}.datepicker table tr td.today:hover,.datepicker table tr td.today:hover:hover,.datepicker table tr td.today.disabled:hover,.datepicker table tr td.today.disabled:hover:hover,.datepicker table tr td.today:active,.datepicker table tr td.today:hover:active,.datepicker table tr td.today.disabled:active,.datepicker table tr td.today.disabled:hover:active,.datepicker table tr td.today.active,.datepicker table tr td.today:hover.active,.datepicker table tr td.today.disabled.active,.datepicker table tr td.today.disabled:hover.active,.datepicker table tr td.today.disabled,.datepicker table tr td.today:hover.disabled,.datepicker table tr td.today.disabled.disabled,.datepicker table tr td.today.disabled:hover.disabled,.datepicker table tr td.today[disabled],.datepicker table tr td.today:hover[disabled],.datepicker table tr td.today.disabled[disabled],.datepicker table tr td.today.disabled:hover[disabled]{background-color:#fdf59a}.datepicker table tr td.today:active,.datepicker table tr td.today:hover:active,.datepicker table tr td.today.disabled:active,.datepicker table tr td.today.disabled:hover:active,.datepicker table tr td.today.active,.datepicker table tr td.today:hover.active,.datepicker table tr td.today.disabled.active,.datepicker table tr td.today.disabled:hover.active{background-color:#fbf069 \9}.datepicker table tr td.today:hover:hover{color:#000}.datepicker table tr td.today.active:hover{color:#fff}.datepicker table tr td.range,.datepicker table tr td.range:hover,.datepicker table tr td.range.disabled,.datepicker table tr td.range.disabled:hover{background:#eee;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.datepicker table tr td.range.today,.datepicker table tr td.range.today:hover,.datepicker table tr td.range.today.disabled,.datepicker table tr td.range.today.disabled:hover{background-color:#f3d17a;background-image:-moz-linear-gradient(top,#f3c17a,#f3e97a);background-image:-ms-linear-gradient(top,#f3c17a,#f3e97a);background-image:-webkit-gradient(linear,0 0,0 100%,from(#f3c17a),to(#f3e97a));background-image:-webkit-linear-gradient(top,#f3c17a,#f3e97a);background-image:-o-linear-gradient(top,#f3c17a,#f3e97a);background-image:linear-gradient(top,#f3c17a,#f3e97a);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#f3c17a', endColorstr='#f3e97a', GradientType=0);border-color:#f3e97a #f3e97a #edde34;border-color:rgba(0,0,0,.1) rgba(0,0,0,.1) rgba(0,0,0,.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.datepicker table tr td.range.today:hover,.datepicker table tr td.range.today:hover:hover,.datepicker table tr td.range.today.disabled:hover,.datepicker table tr td.range.today.disabled:hover:hover,.datepicker table tr td.range.today:active,.datepicker table tr td.range.today:hover:active,.datepicker table tr td.range.today.disabled:active,.datepicker table tr td.range.today.disabled:hover:active,.datepicker table tr td.range.today.active,.datepicker table tr td.range.today:hover.active,.datepicker table tr td.range.today.disabled.active,.datepicker table tr td.range.today.disabled:hover.active,.datepicker table tr td.range.today.disabled,.datepicker table tr td.range.today:hover.disabled,.datepicker table tr td.range.today.disabled.disabled,.datepicker table tr td.range.today.disabled:hover.disabled,.datepicker table tr td.range.today[disabled],.datepicker table tr td.range.today:hover[disabled],.datepicker table tr td.range.today.disabled[disabled],.datepicker table tr td.range.today.disabled:hover[disabled]{background-color:#f3e97a}.datepicker table tr td.range.today:active,.datepicker table tr td.range.today:hover:active,.datepicker table tr td.range.today.disabled:active,.datepicker table tr td.range.today.disabled:hover:active,.datepicker table tr td.range.today.active,.datepicker table tr td.range.today:hover.active,.datepicker table tr td.range.today.disabled.active,.datepicker table tr td.range.today.disabled:hover.active{background-color:#efe24b \9}.datepicker table tr td.selected,.datepicker table tr td.selected:hover,.datepicker table tr td.selected.disabled,.datepicker table tr td.selected.disabled:hover{background-color:#9e9e9e;background-image:-moz-linear-gradient(top,#b3b3b3,gray);background-image:-ms-linear-gradient(top,#b3b3b3,gray);background-image:-webkit-gradient(linear,0 0,0 100%,from(#b3b3b3),to(gray));background-image:-webkit-linear-gradient(top,#b3b3b3,gray);background-image:-o-linear-gradient(top,#b3b3b3,gray);background-image:linear-gradient(top,#b3b3b3,gray);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#b3b3b3', endColorstr='#808080', GradientType=0);border-color:gray #808080 #595959;border-color:rgba(0,0,0,.1) rgba(0,0,0,.1) rgba(0,0,0,.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,.25)}.datepicker table tr td.selected:hover,.datepicker table tr td.selected:hover:hover,.datepicker table tr td.selected.disabled:hover,.datepicker table tr td.selected.disabled:hover:hover,.datepicker table tr td.selected:active,.datepicker table tr td.selected:hover:active,.datepicker table tr td.selected.disabled:active,.datepicker table tr td.selected.disabled:hover:active,.datepicker table tr td.selected.active,.datepicker table tr td.selected:hover.active,.datepicker table tr td.selected.disabled.active,.datepicker table tr td.selected.disabled:hover.active,.datepicker table tr td.selected.disabled,.datepicker table tr td.selected:hover.disabled,.datepicker table tr td.selected.disabled.disabled,.datepicker table tr td.selected.disabled:hover.disabled,.datepicker table tr td.selected[disabled],.datepicker table tr td.selected:hover[disabled],.datepicker table tr td.selected.disabled[disabled],.datepicker table tr td.selected.disabled:hover[disabled]{background-color:gray}.datepicker table tr td.selected:active,.datepicker table tr td.selected:hover:active,.datepicker table tr td.selected.disabled:active,.datepicker table tr td.selected.disabled:hover:active,.datepicker table tr td.selected.active,.datepicker table tr td.selected:hover.active,.datepicker table tr td.selected.disabled.active,.datepicker table tr td.selected.disabled:hover.active{background-color:#666 \9}.datepicker table tr td.active,.datepicker table tr td.active:hover,.datepicker table tr td.active.disabled,.datepicker table tr td.active.disabled:hover{background-color:#006dcc;background-image:-moz-linear-gradient(top,#08c,#04c);background-image:-ms-linear-gradient(top,#08c,#04c);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#04c));background-image:-webkit-linear-gradient(top,#08c,#04c);background-image:-o-linear-gradient(top,#08c,#04c);background-image:linear-gradient(top,#08c,#04c);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);border-color:#04c #04c #002a80;border-color:rgba(0,0,0,.1) rgba(0,0,0,.1) rgba(0,0,0,.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,.25)}.datepicker table tr td.active:hover,.datepicker table tr td.active:hover:hover,.datepicker table tr td.active.disabled:hover,.datepicker table tr td.active.disabled:hover:hover,.datepicker table tr td.active:active,.datepicker table tr td.active:hover:active,.datepicker table tr td.active.disabled:active,.datepicker table tr td.active.disabled:hover:active,.datepicker table tr td.active.active,.datepicker table tr td.active:hover.active,.datepicker table tr td.active.disabled.active,.datepicker table tr td.active.disabled:hover.active,.datepicker table tr td.active.disabled,.datepicker table tr td.active:hover.disabled,.datepicker table tr td.active.disabled.disabled,.datepicker table tr td.active.disabled:hover.disabled,.datepicker table tr td.active[disabled],.datepicker table tr td.active:hover[disabled],.datepicker table tr td.active.disabled[disabled],.datepicker table tr td.active.disabled:hover[disabled]{background-color:#04c}.datepicker table tr td.active:active,.datepicker table tr td.active:hover:active,.datepicker table tr td.active.disabled:active,.datepicker table tr td.active.disabled:hover:active,.datepicker table tr td.active.active,.datepicker table tr td.active:hover.active,.datepicker table tr td.active.disabled.active,.datepicker table tr td.active.disabled:hover.active{background-color:#039 \9}.datepicker table tr td span{display:block;width:23%;height:54px;line-height:54px;float:left;margin:1%;cursor:pointer;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.datepicker table tr td span:hover{background:#eee}.datepicker table tr td span.disabled,.datepicker table tr td span.disabled:hover{background:0 0;color:#999;cursor:default}.datepicker table tr td span.active,.datepicker table tr td span.active:hover,.datepicker table tr td span.active.disabled,.datepicker table tr td span.active.disabled:hover{background-color:#006dcc;background-image:-moz-linear-gradient(top,#08c,#04c);background-image:-ms-linear-gradient(top,#08c,#04c);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#04c));background-image:-webkit-linear-gradient(top,#08c,#04c);background-image:-o-linear-gradient(top,#08c,#04c);background-image:linear-gradient(top,#08c,#04c);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);border-color:#04c #04c #002a80;border-color:rgba(0,0,0,.1) rgba(0,0,0,.1) rgba(0,0,0,.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,.25)}.datepicker table tr td span.active:hover,.datepicker table tr td span.active:hover:hover,.datepicker table tr td span.active.disabled:hover,.datepicker table tr td span.active.disabled:hover:hover,.datepicker table tr td span.active:active,.datepicker table tr td span.active:hover:active,.datepicker table tr td span.active.disabled:active,.datepicker table tr td span.active.disabled:hover:active,.datepicker table tr td span.active.active,.datepicker table tr td span.active:hover.active,.datepicker table tr td span.active.disabled.active,.datepicker table tr td span.active.disabled:hover.active,.datepicker table tr td span.active.disabled,.datepicker table tr td span.active:hover.disabled,.datepicker table tr td span.active.disabled.disabled,.datepicker table tr td span.active.disabled:hover.disabled,.datepicker table tr td span.active[disabled],.datepicker table tr td span.active:hover[disabled],.datepicker table tr td span.active.disabled[disabled],.datepicker table tr td span.active.disabled:hover[disabled]{background-color:#04c}.datepicker table tr td span.active:active,.datepicker table tr td span.active:hover:active,.datepicker table tr td span.active.disabled:active,.datepicker table tr td span.active.disabled:hover:active,.datepicker table tr td span.active.active,.datepicker table tr td span.active:hover.active,.datepicker table tr td span.active.disabled.active,.datepicker table tr td span.active.disabled:hover.active{background-color:#039 \9}.datepicker table tr td span.old,.datepicker table tr td span.new{color:#999}.datepicker .datepicker-switch{width:145px}.datepicker thead tr:first-child th,.datepicker tfoot tr th{cursor:pointer}.datepicker thead tr:first-child th:hover,.datepicker tfoot tr th:hover{background:#eee}.datepicker .cw{font-size:10px;width:12px;padding:0 2px 0 5px;vertical-align:middle}.datepicker thead tr:first-child .cw{cursor:default;background-color:transparent}.input-append.date .add-on,.input-prepend.date .add-on{cursor:pointer}.input-append.date .add-on i,.input-prepend.date .add-on i{margin-top:3px}.input-daterange input{text-align:center}.input-daterange input:first-child{-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px}.input-daterange input:last-child{-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0}.input-daterange .add-on{display:inline-block;width:auto;min-width:16px;height:20px;padding:4px 5px;font-weight:400;line-height:20px;text-align:center;text-shadow:0 1px 0 #fff;vertical-align:middle;background-color:#eee;border:1px solid #ccc;margin-left:-5px;margin-right:-5px}.datepicker.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;float:left;display:none;min-width:160px;list-style:none;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box;*border-right-width:2px;*border-bottom-width:2px;color:#333;font-size:13px;line-height:20px}.datepicker.dropdown-menu th,.datepicker.datepicker-inline th,.datepicker.dropdown-menu td,.datepicker.datepicker-inline td{padding:4px 5px}
--------------------------------------------------------------------------------
/server/public/bootstrap-datepicker/css/bootstrap-datepicker.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Datepicker for Bootstrap v1.4.0 (https://github.com/eternicode/bootstrap-datepicker)
3 | *
4 | * Copyright 2012 Stefan Petre
5 | * Improvements by Andrew Rowls
6 | * Licensed under the Apache License v2.0 (http://www.apache.org/licenses/LICENSE-2.0)
7 | */
8 | .datepicker {
9 | padding: 4px;
10 | -webkit-border-radius: 4px;
11 | -moz-border-radius: 4px;
12 | border-radius: 4px;
13 | direction: ltr;
14 | }
15 | .datepicker-inline {
16 | width: 220px;
17 | }
18 | .datepicker.datepicker-rtl {
19 | direction: rtl;
20 | }
21 | .datepicker.datepicker-rtl table tr td span {
22 | float: right;
23 | }
24 | .datepicker-dropdown {
25 | top: 0;
26 | left: 0;
27 | }
28 | .datepicker-dropdown:before {
29 | content: '';
30 | display: inline-block;
31 | border-left: 7px solid transparent;
32 | border-right: 7px solid transparent;
33 | border-bottom: 7px solid #ccc;
34 | border-top: 0;
35 | border-bottom-color: rgba(0, 0, 0, 0.2);
36 | position: absolute;
37 | }
38 | .datepicker-dropdown:after {
39 | content: '';
40 | display: inline-block;
41 | border-left: 6px solid transparent;
42 | border-right: 6px solid transparent;
43 | border-bottom: 6px solid #ffffff;
44 | border-top: 0;
45 | position: absolute;
46 | }
47 | .datepicker-dropdown.datepicker-orient-left:before {
48 | left: 6px;
49 | }
50 | .datepicker-dropdown.datepicker-orient-left:after {
51 | left: 7px;
52 | }
53 | .datepicker-dropdown.datepicker-orient-right:before {
54 | right: 6px;
55 | }
56 | .datepicker-dropdown.datepicker-orient-right:after {
57 | right: 7px;
58 | }
59 | .datepicker-dropdown.datepicker-orient-top:before {
60 | top: -7px;
61 | }
62 | .datepicker-dropdown.datepicker-orient-top:after {
63 | top: -6px;
64 | }
65 | .datepicker-dropdown.datepicker-orient-bottom:before {
66 | bottom: -7px;
67 | border-bottom: 0;
68 | border-top: 7px solid #999;
69 | }
70 | .datepicker-dropdown.datepicker-orient-bottom:after {
71 | bottom: -6px;
72 | border-bottom: 0;
73 | border-top: 6px solid #ffffff;
74 | }
75 | .datepicker > div {
76 | display: none;
77 | }
78 | .datepicker.days .datepicker-days,
79 | .datepicker.months .datepicker-months,
80 | .datepicker.years .datepicker-years {
81 | display: block;
82 | }
83 | .datepicker table {
84 | margin: 0;
85 | -webkit-touch-callout: none;
86 | -webkit-user-select: none;
87 | -khtml-user-select: none;
88 | -moz-user-select: none;
89 | -ms-user-select: none;
90 | user-select: none;
91 | }
92 | .datepicker td,
93 | .datepicker th {
94 | text-align: center;
95 | width: 20px;
96 | height: 20px;
97 | -webkit-border-radius: 4px;
98 | -moz-border-radius: 4px;
99 | border-radius: 4px;
100 | border: none;
101 | }
102 | .table-striped .datepicker table tr td,
103 | .table-striped .datepicker table tr th {
104 | background-color: transparent;
105 | }
106 | .datepicker table tr td.day:hover,
107 | .datepicker table tr td.day.focused {
108 | background: #eeeeee;
109 | cursor: pointer;
110 | }
111 | .datepicker table tr td.old,
112 | .datepicker table tr td.new {
113 | color: #999999;
114 | }
115 | .datepicker table tr td.disabled,
116 | .datepicker table tr td.disabled:hover {
117 | background: none;
118 | color: #999999;
119 | cursor: default;
120 | }
121 | .datepicker table tr td.today,
122 | .datepicker table tr td.today:hover,
123 | .datepicker table tr td.today.disabled,
124 | .datepicker table tr td.today.disabled:hover {
125 | background-color: #fde19a;
126 | background-image: -moz-linear-gradient(top, #fdd49a, #fdf59a);
127 | background-image: -ms-linear-gradient(top, #fdd49a, #fdf59a);
128 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fdd49a), to(#fdf59a));
129 | background-image: -webkit-linear-gradient(top, #fdd49a, #fdf59a);
130 | background-image: -o-linear-gradient(top, #fdd49a, #fdf59a);
131 | background-image: linear-gradient(top, #fdd49a, #fdf59a);
132 | background-repeat: repeat-x;
133 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fdd49a', endColorstr='#fdf59a', GradientType=0);
134 | border-color: #fdf59a #fdf59a #fbed50;
135 | border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
136 | filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
137 | color: #000;
138 | }
139 | .datepicker table tr td.today:hover,
140 | .datepicker table tr td.today:hover:hover,
141 | .datepicker table tr td.today.disabled:hover,
142 | .datepicker table tr td.today.disabled:hover:hover,
143 | .datepicker table tr td.today:active,
144 | .datepicker table tr td.today:hover:active,
145 | .datepicker table tr td.today.disabled:active,
146 | .datepicker table tr td.today.disabled:hover:active,
147 | .datepicker table tr td.today.active,
148 | .datepicker table tr td.today:hover.active,
149 | .datepicker table tr td.today.disabled.active,
150 | .datepicker table tr td.today.disabled:hover.active,
151 | .datepicker table tr td.today.disabled,
152 | .datepicker table tr td.today:hover.disabled,
153 | .datepicker table tr td.today.disabled.disabled,
154 | .datepicker table tr td.today.disabled:hover.disabled,
155 | .datepicker table tr td.today[disabled],
156 | .datepicker table tr td.today:hover[disabled],
157 | .datepicker table tr td.today.disabled[disabled],
158 | .datepicker table tr td.today.disabled:hover[disabled] {
159 | background-color: #fdf59a;
160 | }
161 | .datepicker table tr td.today:active,
162 | .datepicker table tr td.today:hover:active,
163 | .datepicker table tr td.today.disabled:active,
164 | .datepicker table tr td.today.disabled:hover:active,
165 | .datepicker table tr td.today.active,
166 | .datepicker table tr td.today:hover.active,
167 | .datepicker table tr td.today.disabled.active,
168 | .datepicker table tr td.today.disabled:hover.active {
169 | background-color: #fbf069 \9;
170 | }
171 | .datepicker table tr td.today:hover:hover {
172 | color: #000;
173 | }
174 | .datepicker table tr td.today.active:hover {
175 | color: #fff;
176 | }
177 | .datepicker table tr td.range,
178 | .datepicker table tr td.range:hover,
179 | .datepicker table tr td.range.disabled,
180 | .datepicker table tr td.range.disabled:hover {
181 | background: #eeeeee;
182 | -webkit-border-radius: 0;
183 | -moz-border-radius: 0;
184 | border-radius: 0;
185 | }
186 | .datepicker table tr td.range.today,
187 | .datepicker table tr td.range.today:hover,
188 | .datepicker table tr td.range.today.disabled,
189 | .datepicker table tr td.range.today.disabled:hover {
190 | background-color: #f3d17a;
191 | background-image: -moz-linear-gradient(top, #f3c17a, #f3e97a);
192 | background-image: -ms-linear-gradient(top, #f3c17a, #f3e97a);
193 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f3c17a), to(#f3e97a));
194 | background-image: -webkit-linear-gradient(top, #f3c17a, #f3e97a);
195 | background-image: -o-linear-gradient(top, #f3c17a, #f3e97a);
196 | background-image: linear-gradient(top, #f3c17a, #f3e97a);
197 | background-repeat: repeat-x;
198 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f3c17a', endColorstr='#f3e97a', GradientType=0);
199 | border-color: #f3e97a #f3e97a #edde34;
200 | border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
201 | filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
202 | -webkit-border-radius: 0;
203 | -moz-border-radius: 0;
204 | border-radius: 0;
205 | }
206 | .datepicker table tr td.range.today:hover,
207 | .datepicker table tr td.range.today:hover:hover,
208 | .datepicker table tr td.range.today.disabled:hover,
209 | .datepicker table tr td.range.today.disabled:hover:hover,
210 | .datepicker table tr td.range.today:active,
211 | .datepicker table tr td.range.today:hover:active,
212 | .datepicker table tr td.range.today.disabled:active,
213 | .datepicker table tr td.range.today.disabled:hover:active,
214 | .datepicker table tr td.range.today.active,
215 | .datepicker table tr td.range.today:hover.active,
216 | .datepicker table tr td.range.today.disabled.active,
217 | .datepicker table tr td.range.today.disabled:hover.active,
218 | .datepicker table tr td.range.today.disabled,
219 | .datepicker table tr td.range.today:hover.disabled,
220 | .datepicker table tr td.range.today.disabled.disabled,
221 | .datepicker table tr td.range.today.disabled:hover.disabled,
222 | .datepicker table tr td.range.today[disabled],
223 | .datepicker table tr td.range.today:hover[disabled],
224 | .datepicker table tr td.range.today.disabled[disabled],
225 | .datepicker table tr td.range.today.disabled:hover[disabled] {
226 | background-color: #f3e97a;
227 | }
228 | .datepicker table tr td.range.today:active,
229 | .datepicker table tr td.range.today:hover:active,
230 | .datepicker table tr td.range.today.disabled:active,
231 | .datepicker table tr td.range.today.disabled:hover:active,
232 | .datepicker table tr td.range.today.active,
233 | .datepicker table tr td.range.today:hover.active,
234 | .datepicker table tr td.range.today.disabled.active,
235 | .datepicker table tr td.range.today.disabled:hover.active {
236 | background-color: #efe24b \9;
237 | }
238 | .datepicker table tr td.selected,
239 | .datepicker table tr td.selected:hover,
240 | .datepicker table tr td.selected.disabled,
241 | .datepicker table tr td.selected.disabled:hover {
242 | background-color: #9e9e9e;
243 | background-image: -moz-linear-gradient(top, #b3b3b3, #808080);
244 | background-image: -ms-linear-gradient(top, #b3b3b3, #808080);
245 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#b3b3b3), to(#808080));
246 | background-image: -webkit-linear-gradient(top, #b3b3b3, #808080);
247 | background-image: -o-linear-gradient(top, #b3b3b3, #808080);
248 | background-image: linear-gradient(top, #b3b3b3, #808080);
249 | background-repeat: repeat-x;
250 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#b3b3b3', endColorstr='#808080', GradientType=0);
251 | border-color: #808080 #808080 #595959;
252 | border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
253 | filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
254 | color: #fff;
255 | text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
256 | }
257 | .datepicker table tr td.selected:hover,
258 | .datepicker table tr td.selected:hover:hover,
259 | .datepicker table tr td.selected.disabled:hover,
260 | .datepicker table tr td.selected.disabled:hover:hover,
261 | .datepicker table tr td.selected:active,
262 | .datepicker table tr td.selected:hover:active,
263 | .datepicker table tr td.selected.disabled:active,
264 | .datepicker table tr td.selected.disabled:hover:active,
265 | .datepicker table tr td.selected.active,
266 | .datepicker table tr td.selected:hover.active,
267 | .datepicker table tr td.selected.disabled.active,
268 | .datepicker table tr td.selected.disabled:hover.active,
269 | .datepicker table tr td.selected.disabled,
270 | .datepicker table tr td.selected:hover.disabled,
271 | .datepicker table tr td.selected.disabled.disabled,
272 | .datepicker table tr td.selected.disabled:hover.disabled,
273 | .datepicker table tr td.selected[disabled],
274 | .datepicker table tr td.selected:hover[disabled],
275 | .datepicker table tr td.selected.disabled[disabled],
276 | .datepicker table tr td.selected.disabled:hover[disabled] {
277 | background-color: #808080;
278 | }
279 | .datepicker table tr td.selected:active,
280 | .datepicker table tr td.selected:hover:active,
281 | .datepicker table tr td.selected.disabled:active,
282 | .datepicker table tr td.selected.disabled:hover:active,
283 | .datepicker table tr td.selected.active,
284 | .datepicker table tr td.selected:hover.active,
285 | .datepicker table tr td.selected.disabled.active,
286 | .datepicker table tr td.selected.disabled:hover.active {
287 | background-color: #666666 \9;
288 | }
289 | .datepicker table tr td.active,
290 | .datepicker table tr td.active:hover,
291 | .datepicker table tr td.active.disabled,
292 | .datepicker table tr td.active.disabled:hover {
293 | background-color: #006dcc;
294 | background-image: -moz-linear-gradient(top, #0088cc, #0044cc);
295 | background-image: -ms-linear-gradient(top, #0088cc, #0044cc);
296 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));
297 | background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);
298 | background-image: -o-linear-gradient(top, #0088cc, #0044cc);
299 | background-image: linear-gradient(top, #0088cc, #0044cc);
300 | background-repeat: repeat-x;
301 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);
302 | border-color: #0044cc #0044cc #002a80;
303 | border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
304 | filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
305 | color: #fff;
306 | text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
307 | }
308 | .datepicker table tr td.active:hover,
309 | .datepicker table tr td.active:hover:hover,
310 | .datepicker table tr td.active.disabled:hover,
311 | .datepicker table tr td.active.disabled:hover:hover,
312 | .datepicker table tr td.active:active,
313 | .datepicker table tr td.active:hover:active,
314 | .datepicker table tr td.active.disabled:active,
315 | .datepicker table tr td.active.disabled:hover:active,
316 | .datepicker table tr td.active.active,
317 | .datepicker table tr td.active:hover.active,
318 | .datepicker table tr td.active.disabled.active,
319 | .datepicker table tr td.active.disabled:hover.active,
320 | .datepicker table tr td.active.disabled,
321 | .datepicker table tr td.active:hover.disabled,
322 | .datepicker table tr td.active.disabled.disabled,
323 | .datepicker table tr td.active.disabled:hover.disabled,
324 | .datepicker table tr td.active[disabled],
325 | .datepicker table tr td.active:hover[disabled],
326 | .datepicker table tr td.active.disabled[disabled],
327 | .datepicker table tr td.active.disabled:hover[disabled] {
328 | background-color: #0044cc;
329 | }
330 | .datepicker table tr td.active:active,
331 | .datepicker table tr td.active:hover:active,
332 | .datepicker table tr td.active.disabled:active,
333 | .datepicker table tr td.active.disabled:hover:active,
334 | .datepicker table tr td.active.active,
335 | .datepicker table tr td.active:hover.active,
336 | .datepicker table tr td.active.disabled.active,
337 | .datepicker table tr td.active.disabled:hover.active {
338 | background-color: #003399 \9;
339 | }
340 | .datepicker table tr td span {
341 | display: block;
342 | width: 23%;
343 | height: 54px;
344 | line-height: 54px;
345 | float: left;
346 | margin: 1%;
347 | cursor: pointer;
348 | -webkit-border-radius: 4px;
349 | -moz-border-radius: 4px;
350 | border-radius: 4px;
351 | }
352 | .datepicker table tr td span:hover {
353 | background: #eeeeee;
354 | }
355 | .datepicker table tr td span.disabled,
356 | .datepicker table tr td span.disabled:hover {
357 | background: none;
358 | color: #999999;
359 | cursor: default;
360 | }
361 | .datepicker table tr td span.active,
362 | .datepicker table tr td span.active:hover,
363 | .datepicker table tr td span.active.disabled,
364 | .datepicker table tr td span.active.disabled:hover {
365 | background-color: #006dcc;
366 | background-image: -moz-linear-gradient(top, #0088cc, #0044cc);
367 | background-image: -ms-linear-gradient(top, #0088cc, #0044cc);
368 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));
369 | background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);
370 | background-image: -o-linear-gradient(top, #0088cc, #0044cc);
371 | background-image: linear-gradient(top, #0088cc, #0044cc);
372 | background-repeat: repeat-x;
373 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);
374 | border-color: #0044cc #0044cc #002a80;
375 | border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
376 | filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
377 | color: #fff;
378 | text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
379 | }
380 | .datepicker table tr td span.active:hover,
381 | .datepicker table tr td span.active:hover:hover,
382 | .datepicker table tr td span.active.disabled:hover,
383 | .datepicker table tr td span.active.disabled:hover:hover,
384 | .datepicker table tr td span.active:active,
385 | .datepicker table tr td span.active:hover:active,
386 | .datepicker table tr td span.active.disabled:active,
387 | .datepicker table tr td span.active.disabled:hover:active,
388 | .datepicker table tr td span.active.active,
389 | .datepicker table tr td span.active:hover.active,
390 | .datepicker table tr td span.active.disabled.active,
391 | .datepicker table tr td span.active.disabled:hover.active,
392 | .datepicker table tr td span.active.disabled,
393 | .datepicker table tr td span.active:hover.disabled,
394 | .datepicker table tr td span.active.disabled.disabled,
395 | .datepicker table tr td span.active.disabled:hover.disabled,
396 | .datepicker table tr td span.active[disabled],
397 | .datepicker table tr td span.active:hover[disabled],
398 | .datepicker table tr td span.active.disabled[disabled],
399 | .datepicker table tr td span.active.disabled:hover[disabled] {
400 | background-color: #0044cc;
401 | }
402 | .datepicker table tr td span.active:active,
403 | .datepicker table tr td span.active:hover:active,
404 | .datepicker table tr td span.active.disabled:active,
405 | .datepicker table tr td span.active.disabled:hover:active,
406 | .datepicker table tr td span.active.active,
407 | .datepicker table tr td span.active:hover.active,
408 | .datepicker table tr td span.active.disabled.active,
409 | .datepicker table tr td span.active.disabled:hover.active {
410 | background-color: #003399 \9;
411 | }
412 | .datepicker table tr td span.old,
413 | .datepicker table tr td span.new {
414 | color: #999999;
415 | }
416 | .datepicker .datepicker-switch {
417 | width: 145px;
418 | }
419 | .datepicker thead tr:first-child th,
420 | .datepicker tfoot tr th {
421 | cursor: pointer;
422 | }
423 | .datepicker thead tr:first-child th:hover,
424 | .datepicker tfoot tr th:hover {
425 | background: #eeeeee;
426 | }
427 | .datepicker .cw {
428 | font-size: 10px;
429 | width: 12px;
430 | padding: 0 2px 0 5px;
431 | vertical-align: middle;
432 | }
433 | .datepicker thead tr:first-child .cw {
434 | cursor: default;
435 | background-color: transparent;
436 | }
437 | .input-append.date .add-on,
438 | .input-prepend.date .add-on {
439 | cursor: pointer;
440 | }
441 | .input-append.date .add-on i,
442 | .input-prepend.date .add-on i {
443 | margin-top: 3px;
444 | }
445 | .input-daterange input {
446 | text-align: center;
447 | }
448 | .input-daterange input:first-child {
449 | -webkit-border-radius: 3px 0 0 3px;
450 | -moz-border-radius: 3px 0 0 3px;
451 | border-radius: 3px 0 0 3px;
452 | }
453 | .input-daterange input:last-child {
454 | -webkit-border-radius: 0 3px 3px 0;
455 | -moz-border-radius: 0 3px 3px 0;
456 | border-radius: 0 3px 3px 0;
457 | }
458 | .input-daterange .add-on {
459 | display: inline-block;
460 | width: auto;
461 | min-width: 16px;
462 | height: 18px;
463 | padding: 4px 5px;
464 | font-weight: normal;
465 | line-height: 18px;
466 | text-align: center;
467 | text-shadow: 0 1px 0 #ffffff;
468 | vertical-align: middle;
469 | background-color: #eeeeee;
470 | border: 1px solid #ccc;
471 | margin-left: -5px;
472 | margin-right: -5px;
473 | }
474 |
--------------------------------------------------------------------------------
/server/public/bootstrap/css/bootstrap-theme.min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap v3.3.4 (http://getbootstrap.com)
3 | * Copyright 2011-2015 Twitter, Inc.
4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
5 | */.btn-danger,.btn-default,.btn-info,.btn-primary,.btn-success,.btn-warning{text-shadow:0 -1px 0 rgba(0,0,0,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-danger.active,.btn-danger:active,.btn-default.active,.btn-default:active,.btn-info.active,.btn-info:active,.btn-primary.active,.btn-primary:active,.btn-success.active,.btn-success:active,.btn-warning.active,.btn-warning:active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-danger .badge,.btn-default .badge,.btn-info .badge,.btn-primary .badge,.btn-success .badge,.btn-warning .badge{text-shadow:none}.btn.active,.btn:active{background-image:none}.btn-default{text-shadow:0 1px 0 #fff;background-image:-webkit-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-o-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e0e0e0));background-image:linear-gradient(to bottom,#fff 0,#e0e0e0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#dbdbdb;border-color:#ccc}.btn-default:focus,.btn-default:hover{background-color:#e0e0e0;background-position:0 -15px}.btn-default.active,.btn-default:active{background-color:#e0e0e0;border-color:#dbdbdb}.btn-default.disabled,.btn-default:disabled,.btn-default[disabled]{background-color:#e0e0e0;background-image:none}.btn-primary{background-image:-webkit-linear-gradient(top,#337ab7 0,#265a88 100%);background-image:-o-linear-gradient(top,#337ab7 0,#265a88 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#265a88));background-image:linear-gradient(to bottom,#337ab7 0,#265a88 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#245580}.btn-primary:focus,.btn-primary:hover{background-color:#265a88;background-position:0 -15px}.btn-primary.active,.btn-primary:active{background-color:#265a88;border-color:#245580}.btn-primary.disabled,.btn-primary:disabled,.btn-primary[disabled]{background-color:#265a88;background-image:none}.btn-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#419641));background-image:linear-gradient(to bottom,#5cb85c 0,#419641 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#3e8f3e}.btn-success:focus,.btn-success:hover{background-color:#419641;background-position:0 -15px}.btn-success.active,.btn-success:active{background-color:#419641;border-color:#3e8f3e}.btn-success.disabled,.btn-success:disabled,.btn-success[disabled]{background-color:#419641;background-image:none}.btn-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#2aabd2));background-image:linear-gradient(to bottom,#5bc0de 0,#2aabd2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#28a4c9}.btn-info:focus,.btn-info:hover{background-color:#2aabd2;background-position:0 -15px}.btn-info.active,.btn-info:active{background-color:#2aabd2;border-color:#28a4c9}.btn-info.disabled,.btn-info:disabled,.btn-info[disabled]{background-color:#2aabd2;background-image:none}.btn-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#eb9316));background-image:linear-gradient(to bottom,#f0ad4e 0,#eb9316 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#e38d13}.btn-warning:focus,.btn-warning:hover{background-color:#eb9316;background-position:0 -15px}.btn-warning.active,.btn-warning:active{background-color:#eb9316;border-color:#e38d13}.btn-warning.disabled,.btn-warning:disabled,.btn-warning[disabled]{background-color:#eb9316;background-image:none}.btn-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c12e2a));background-image:linear-gradient(to bottom,#d9534f 0,#c12e2a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#b92c28}.btn-danger:focus,.btn-danger:hover{background-color:#c12e2a;background-position:0 -15px}.btn-danger.active,.btn-danger:active{background-color:#c12e2a;border-color:#b92c28}.btn-danger.disabled,.btn-danger:disabled,.btn-danger[disabled]{background-color:#c12e2a;background-image:none}.img-thumbnail,.thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{background-color:#e8e8e8;background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{background-color:#2e6da4;background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}.navbar-default{background-image:-webkit-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-o-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#f8f8f8));background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075)}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.open>a{background-image:-webkit-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-o-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dbdbdb),to(#e2e2e2));background-image:linear-gradient(to bottom,#dbdbdb 0,#e2e2e2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.075);box-shadow:inset 0 3px 9px rgba(0,0,0,.075)}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,.25)}.navbar-inverse{background-image:-webkit-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-o-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#3c3c3c),to(#222));background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.open>a{background-image:-webkit-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-o-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#080808),to(#0f0f0f));background-image:linear-gradient(to bottom,#080808 0,#0f0f0f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.25);box-shadow:inset 0 3px 9px rgba(0,0,0,.25)}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,.25)}.navbar-fixed-bottom,.navbar-fixed-top,.navbar-static-top{border-radius:0}@media (max-width:767px){.navbar .navbar-nav .open .dropdown-menu>.active>a,.navbar .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}}.alert{text-shadow:0 1px 0 rgba(255,255,255,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05)}.alert-success{background-image:-webkit-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#c8e5bc));background-image:linear-gradient(to bottom,#dff0d8 0,#c8e5bc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);background-repeat:repeat-x;border-color:#b2dba1}.alert-info{background-image:-webkit-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#b9def0));background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);background-repeat:repeat-x;border-color:#9acfea}.alert-warning{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#f8efc0));background-image:linear-gradient(to bottom,#fcf8e3 0,#f8efc0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);background-repeat:repeat-x;border-color:#f5e79e}.alert-danger{background-image:-webkit-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-o-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#e7c3c3));background-image:linear-gradient(to bottom,#f2dede 0,#e7c3c3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);background-repeat:repeat-x;border-color:#dca7a7}.progress{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#ebebeb),to(#f5f5f5));background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x}.progress-bar{background-image:-webkit-linear-gradient(top,#337ab7 0,#286090 100%);background-image:-o-linear-gradient(top,#337ab7 0,#286090 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#286090));background-image:linear-gradient(to bottom,#337ab7 0,#286090 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);background-repeat:repeat-x}.progress-bar-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#449d44));background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);background-repeat:repeat-x}.progress-bar-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#31b0d5));background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);background-repeat:repeat-x}.progress-bar-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#ec971f));background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);background-repeat:repeat-x}.progress-bar-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c9302c));background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);background-repeat:repeat-x}.progress-bar-striped{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{text-shadow:0 -1px 0 #286090;background-image:-webkit-linear-gradient(top,#337ab7 0,#2b669a 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2b669a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2b669a));background-image:linear-gradient(to bottom,#337ab7 0,#2b669a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);background-repeat:repeat-x;border-color:#2b669a}.list-group-item.active .badge,.list-group-item.active:focus .badge,.list-group-item.active:hover .badge{text-shadow:none}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.05);box-shadow:0 1px 2px rgba(0,0,0,.05)}.panel-default>.panel-heading{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.panel-primary>.panel-heading{background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}.panel-success>.panel-heading{background-image:-webkit-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#d0e9c6));background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);background-repeat:repeat-x}.panel-info>.panel-heading{background-image:-webkit-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#c4e3f3));background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);background-repeat:repeat-x}.panel-warning>.panel-heading{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#faf2cc));background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);background-repeat:repeat-x}.panel-danger>.panel-heading{background-image:-webkit-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-o-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#ebcccc));background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);background-repeat:repeat-x}.well{background-image:-webkit-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#e8e8e8),to(#f5f5f5));background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x;border-color:#dcdcdc;-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1)}
--------------------------------------------------------------------------------