listwindow.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. /* global $ */
  2. const { ipcRenderer, remote, clipboard } = require('electron')
  3. const LiveMe = remote.getGlobal('LiveMe')
  4. const appSettings = require('electron-settings')
  5. const DataManager = remote.getGlobal('DataManager')
  6. let winType = 0
  7. let userid = ''
  8. let userinfo
  9. let maxCount = 0
  10. let totalCount = 0
  11. let currentPage = 1
  12. let threads = 0
  13. let scrollBusy = false
  14. let filters = { countryCode: '', seen: true, active: false }
  15. let MAX_PAGE_SIZE = 50
  16. const cclist = [
  17. [ 'All Countries', '-' ], [ 'Afghanistan', 'AF' ], [ 'Albania', 'AL' ], [ 'Algeria', 'DZ' ], [ 'American Samoa', 'AS' ], [ 'Andorra', 'AD' ],
  18. [ 'Angola', 'AO' ], [ 'Anguilla', 'AI' ], [ 'Antarctica', 'AQ' ], [ 'Antigua and Barbuda', 'AG' ], [ 'Argentina', 'AR' ], [ 'Armenia', 'AM' ],
  19. [ 'Aruba', 'AW' ], [ 'Australia', 'AU' ], [ 'Austria', 'AT' ], [ 'Azerbaijan', 'AZ' ], [ 'Bahamas', 'BS' ], [ 'Bahrain', 'BH' ],
  20. [ 'Bangladesh', 'BD' ], [ 'Barbados', 'BB' ], [ 'Belarus', 'BY' ], [ 'Belgium', 'BE' ], [ 'Belize', 'BZ' ], [ 'Benin', 'BJ' ],
  21. [ 'Bermuda', 'BM' ], [ 'Bhutan', 'BT' ], [ 'Bolivia', 'BO' ], [ 'Bosnia-Herzegovina', 'BA' ], [ 'Botswana', 'BW' ], [ 'Bouvet Island', 'BV' ],
  22. [ 'Brazil', 'BR' ], [ 'British Indian Ocean Territory', 'IO' ], [ 'Brunei Darussalam', 'BN' ], [ 'Bulgaria', 'BG' ], [ 'Burkina Faso', 'BF' ], [ 'Burundi', 'BI' ],
  23. [ 'Cambodia', 'KH' ], [ 'Cameroon', 'CM' ], [ 'Canada', 'CA' ], [ 'Cape Verde', 'CV' ], [ 'Cayman Islands', 'KY' ], [ 'Central African Republic', 'CF' ],
  24. [ 'Chad', 'TD' ], [ 'Chile', 'CL' ], [ 'China', 'CN' ], [ 'Christmas Island', 'CX' ], [ 'Cocos (Keeling) Islands', 'CC' ], [ 'Colombia', 'CO' ],
  25. [ 'Comoros', 'KM' ], [ 'Congo', 'CG' ], [ 'Congo, Dem. Republic', 'CD' ], [ 'Cook Islands', 'CK' ], [ 'Costa Rica', 'CR' ], [ 'Croatia', 'HR' ],
  26. [ 'Cuba', 'CU' ], [ 'Cyprus', 'CY' ], [ 'Czech Rep.', 'CZ' ], [ 'Denmark', 'DK' ], [ 'Djibouti', 'DJ' ], [ 'Dominica', 'DM' ],
  27. [ 'Dominican Republic', 'DO' ], [ 'Ecuador', 'EC' ], [ 'Egypt', 'EG' ], [ 'El Salvador', 'SV' ], [ 'Equatorial Guinea', 'GQ' ], [ 'Eritrea', 'ER' ],
  28. [ 'Estonia', 'EE' ], [ 'Ethiopia', 'ET' ], [ 'European Union', 'EU.INT' ], [ 'Falkland Islands (Malvinas)', 'FK' ], [ 'Faroe Islands', 'FO' ], [ 'Fiji', 'FJ' ],
  29. [ 'Finland', 'FI' ], [ 'France', 'FR' ], [ 'French Guiana', 'GF' ], [ 'French Southern Territories', 'TF' ], [ 'Gabon', 'GA' ], [ 'Gambia', 'GM' ],
  30. [ 'Georgia', 'GE' ], [ 'Germany', 'DE' ], [ 'Ghana', 'GH' ], [ 'Gibraltar', 'GI' ], [ 'Great Britain', 'GB' ], [ 'Greece', 'GR' ],
  31. [ 'Greenland', 'GL' ], [ 'Grenada', 'GD' ], [ 'Guadeloupe (French)', 'GP' ], [ 'Guam (USA)', 'GU' ], [ 'Guatemala', 'GT' ], [ 'Guernsey', 'GG' ],
  32. [ 'Guinea', 'GN' ], [ 'Guinea Bissau', 'GW' ], [ 'Guyana', 'GY' ], [ 'Haiti', 'HT' ], [ 'Heard Island and McDonald Islands', 'HM' ], [ 'Honduras', 'HN' ],
  33. [ 'Hong Kong', 'HK' ], [ 'Hungary', 'HU' ], [ 'Iceland', 'IS' ], [ 'India', 'IN' ], [ 'Indonesia', 'ID' ], [ 'International', 'INT' ],
  34. [ 'Iran', 'IR' ], [ 'Iraq', 'IQ' ], [ 'Ireland', 'IE' ], [ 'Isle of Man', 'IM' ], [ 'Israel', 'IL' ], [ 'Italy', 'IT' ],
  35. [ 'Ivory Coast', 'CI' ], [ 'Jamaica', 'JM' ], [ 'Japan', 'JP' ], [ 'Jersey', 'JE' ], [ 'Jordan', 'JO' ], [ 'Kazakhstan', 'KZ' ],
  36. [ 'Kenya', 'KE' ], [ 'Kiribati', 'KI' ], [ 'Korea-North', 'KP' ], [ 'Korea-South', 'KR' ], [ 'Kuwait', 'KW' ], [ 'Kyrgyzstan', 'KG' ],
  37. [ 'Laos', 'LA' ], [ 'Latvia', 'LV' ], [ 'Lebanon', 'LB' ], [ 'Lesotho', 'LS' ], [ 'Liberia', 'LR' ], [ 'Libya', 'LY' ],
  38. [ 'Liechtenstein', 'LI' ], [ 'Lithuania', 'LT' ], [ 'Luxembourg', 'LU' ], [ 'Macau', 'MO' ], [ 'Macedonia', 'MK' ], [ 'Madagascar', 'MG' ],
  39. [ 'Malawi', 'MW' ], [ 'Malaysia', 'MY' ], [ 'Maldives', 'MV' ], [ 'Mali', 'ML' ], [ 'Malta', 'MT' ], [ 'Marshall Islands', 'MH' ],
  40. [ 'Martinique (French)', 'MQ' ], [ 'Mauritania', 'MR' ], [ 'Mauritius', 'MU' ], [ 'Mayotte', 'YT' ], [ 'Mexico', 'MX' ], [ 'Micronesia', 'FM' ],
  41. [ 'Moldova', 'MD' ], [ 'Monaco', 'MC' ], [ 'Mongolia', 'MN' ], [ 'Montenegro', 'ME' ], [ 'Montserrat', 'MS' ], [ 'Morocco', 'MA' ],
  42. [ 'Mozambique', 'MZ' ], [ 'Myanmar', 'MM' ], [ 'Namibia', 'NA' ], [ 'Nauru', 'NR' ], [ 'Nepal', 'NP' ], [ 'Netherlands', 'NL' ],
  43. [ 'Netherlands Antilles', 'AN' ], [ 'New Caledonia (French)', 'NC' ], [ 'New Zealand', 'NZ' ], [ 'Nicaragua', 'NI' ], [ 'Niger', 'NE' ], [ 'Nigeria', 'NG' ],
  44. [ 'Niue', 'NU' ], [ 'Norfolk Island', 'NF' ], [ 'Northern Mariana Islands', 'MP' ], [ 'Norway', 'NO' ], [ 'Oman', 'OM' ], [ 'Pakistan', 'PK' ],
  45. [ 'Palau', 'PW' ], [ 'Panama', 'PA' ], [ 'Papua New Guinea', 'PG' ], [ 'Paraguay', 'PY' ], [ 'Peru', 'PE' ], [ 'Philippines', 'PH' ],
  46. [ 'Pitcairn Island', 'PN' ], [ 'Poland', 'PL' ], [ 'Polynesia (French)', 'PF' ], [ 'Portugal', 'PT' ], [ 'Puerto Rico', 'PR' ], [ 'Qatar', 'QA' ],
  47. [ 'Reunion (French)', 'RE' ], [ 'Romania', 'RO' ], [ 'Russia', 'RU' ], [ 'Rwanda', 'RW' ], [ 'Saint Helena', 'SH' ], [ 'Saint Kitts and Nevis Anguilla', 'KN' ],
  48. [ 'Saint Lucia', 'LC' ], [ 'Saint Pierre and Miquelon', 'PM' ], [ 'Saint Vincent and Grenadines', 'VC' ], [ 'Samoa', 'WS' ], [ 'San Marino', 'SM' ], [ 'Sao Tome and Principe', 'ST' ],
  49. [ 'Saudi Arabia', 'SA' ], [ 'Senegal', 'SN' ], [ 'Serbia', 'RS' ], [ 'Seychelles', 'SC' ], [ 'Sierra Leone', 'SL' ], [ 'Singapore', 'SG' ],
  50. [ 'Slovakia', 'SK' ], [ 'Slovenia', 'SI' ], [ 'Solomon Islands', 'SB' ], [ 'Somalia', 'SO' ], [ 'South Africa', 'ZA' ], [ 'South Georgia and South Sandwich Islands', 'GS' ],
  51. [ 'South Sudan', 'SS' ], [ 'Spain', 'ES' ], [ 'Sri Lanka', 'LK' ], [ 'Sudan', 'SD' ], [ 'Suriname', 'SR' ], [ 'Svalbard and Jan Mayen Islands', 'SJ' ],
  52. [ 'Swaziland', 'SZ' ], [ 'Sweden', 'SE' ], [ 'Switzerland', 'CH' ], [ 'Syria', 'SY' ], [ 'Taiwan', 'TW' ], [ 'Tajikistan', 'TJ' ],
  53. [ 'Tanzania', 'TZ' ], [ 'Thailand', 'TH' ], [ 'Togo', 'TG' ], [ 'Tokelau', 'TK' ], [ 'Tonga', 'TO' ], [ 'Trinidad and Tobago', 'TT' ],
  54. [ 'Tunisia', 'TN' ], [ 'Turkey', 'TR' ], [ 'Turkmenistan', 'TM' ], [ 'Turks and Caicos Islands', 'TC' ], [ 'Tuvalu', 'TV' ], [ 'U.K.', 'UK' ],
  55. [ 'USA', 'US' ], [ 'USA Minor Outlying Islands', 'UM' ], [ 'Uganda', 'UG' ], [ 'Ukraine', 'UA' ], [ 'United Arab Emirates', 'AE' ], [ 'Uruguay', 'UY' ],
  56. [ 'Uzbekistan', 'UZ' ], [ 'Vanuatu', 'VU' ], [ 'Vatican', 'VA' ], [ 'Venezuela', 'VE' ], [ 'Vietnam', 'VN' ], [ 'Virgin Islands (British)', 'VG' ],
  57. [ 'Virgin Islands (USA)', 'VI' ], [ 'Wallis and Futuna Islands', 'WF' ], [ 'Western Sahara', 'EH' ], [ 'Yemen', 'YE' ], [ 'Zambia', 'ZM' ], [ 'Zimbabwe', 'ZW' ]
  58. ]
  59. $(function () {
  60. let u = window.location.href
  61. let q = u.split('?')[1].split('&')
  62. userid = q[1]
  63. winType = parseInt(q[0])
  64. LiveMe.getUserInfo(userid).then(user => {
  65. maxCount = winType > 0 ? user.count_info.following_count : user.count_info.follower_count
  66. document.title = user.user_info.uname + (winType === 0 ? ' Fans' : ' Followings')
  67. $('header h1').html(document.title)
  68. })
  69. setTimeout(() => { startLoad() }, 200)
  70. setImmediate(() => { $('main').show() })
  71. filters.countryCode = ''
  72. filters.seen = true
  73. setImmediate(() => {
  74. $('#countryCode').empty()
  75. for (let i = 0; i < cclist.length; i++) {
  76. $('#countryCode').append(`<option value="${cclist[i][1]}">${cclist[i][0]}</option>`)
  77. }
  78. })
  79. $('main').scroll(function () {
  80. if (($(this).scrollTop() + $(this).height()) > ($('table').height() - 240)) {
  81. if (hasMore === false) return
  82. if (scrollBusy === true) return
  83. scrollBusy = true
  84. currentPage++
  85. if (winType === 1) {
  86. doFollowings()
  87. } else {
  88. doFans()
  89. }
  90. }
  91. })
  92. $('#list-search').bind('paste cut keydown', function () {
  93. setTimeout(() => {
  94. const value = $(this).val().toLowerCase()
  95. if (value.trim().length === 0) {
  96. $('table tr').show()
  97. return
  98. }
  99. $('table tr').each(function () {
  100. const name = $(this).find('h1').first().text().toLowerCase()
  101. const uids = $(this).find('.cell a[onclick]').text().toLowerCase()
  102. if (name.indexOf(value) !== -1 || uids.indexOf(value) !== -1) {
  103. $(this).show()
  104. } else {
  105. $(this).hide()
  106. }
  107. })
  108. }, 500)
  109. })
  110. })
  111. function startLoad () {
  112. $('table.fflist tbody').html('')
  113. scrollBusy = true
  114. currentPage = 1
  115. totalCount = 0
  116. switch (winType) {
  117. case 1: // Followers/Fans
  118. doFollowings()
  119. break
  120. case 0: // Followings
  121. doFans()
  122. break
  123. }
  124. }
  125. function loadMore () {
  126. scrollBusy = true
  127. threads = 0
  128. currentPage++
  129. switch (winType) {
  130. case 1: // Followers/Fans
  131. doFollowings()
  132. break
  133. case 0: // Followings
  134. doFans()
  135. break
  136. }
  137. }
  138. function filterCountry () {
  139. filters.active = $('#countryCode').val()
  140. filters.countryCode = $('#countryCode').val()
  141. startLoad()
  142. }
  143. function toggleSeen () {
  144. if (filters.seen === true) {
  145. filters.seen = false
  146. $('i.icon-eye').addClass('icon-eye-blocked').removeClass('icon-eye')
  147. } else {
  148. filters.seen = true
  149. $('i.icon-eye-blocked').addClass('icon-eye').removeClass('icon-eye-blocked')
  150. }
  151. filters.active = !filters.seen
  152. startLoad()
  153. }
  154. function copyToClipboard (i) { clipboard.writeText(i) }
  155. function closeWindow () { window.close() }
  156. function minimizeWindow () { remote.BrowserWindow.getFocusedWindow().minimize() }
  157. function doFollowings () {
  158. $('footer h2').html('<i class="icon icon-arrow-down bright green"></i>')
  159. LiveMe.getFollowing(userid, currentPage, MAX_PAGE_SIZE).then(results => {
  160. $('footer h2').html('<i class="icon icon-arrow-down dim"></i>')
  161. totalCount += results.length
  162. for (let i = 0; i < results.length; i++) {
  163. if ((filters.seen === true) && (filters.countryCode.length < 2)) {
  164. addEntry(results[i])
  165. } if ((filters.countryCode.length > 1) && (results[i].countryCode === filters.countryCode)) {
  166. if (filters.seen === true) {
  167. addEntry(results[i])
  168. } else if ((filters.seen === false) && (DataManager.wasProfileViewed(results[i].uid) !== false)) {
  169. addEntry(results[i])
  170. }
  171. } else if (filters.countryCode.length < 2) {
  172. if ((filters.seen === false) && (DataManager.wasProfileViewed(results[i].uid) === false)) {
  173. addEntry(results[i])
  174. }
  175. }
  176. }
  177. setTimeout(() => {
  178. scrollBusy = false
  179. $('#list-search').trigger('keydown')
  180. }, 200)
  181. hasMore = results.length >= MAX_PAGE_SIZE
  182. let c = $('table.fflist tbody tr').length
  183. if (filters.seen === false || filters.countryCode.length > 1) {
  184. $('footer h1').html(`Showing ${c} filtered from ${totalCount} of ${maxCount} accounts.`)
  185. } else {
  186. $('footer h1').html(`Showing ${totalCount} of ${maxCount} accounts.`)
  187. }
  188. if (hasMore && ($('table.fflist tbody tr').length < (MAX_PAGE_SIZE * 2))) {
  189. setTimeout(() => {
  190. loadMore()
  191. }, 200)
  192. }
  193. })
  194. }
  195. function doFans () {
  196. $('footer h2').html('<i class="icon icon-arrow-down bright green"></i>')
  197. LiveMe.getFans(userid, currentPage, MAX_PAGE_SIZE).then(results => {
  198. $('footer h2').html('<i class="icon icon-arrow-down dim"></i>')
  199. totalCount += results.length
  200. for (let i = 0; i < results.length; i++) {
  201. if ((filters.seen === true) && (filters.countryCode.length < 2)) {
  202. addEntry(results[i])
  203. } if ((filters.countryCode.length > 1) && (results[i].countryCode === filters.countryCode)) {
  204. if (filters.seen === true) {
  205. addEntry(results[i])
  206. } else if ((filters.seen === false) && (DataManager.wasProfileViewed(results[i].uid) !== false)) {
  207. addEntry(results[i])
  208. }
  209. } else if (filters.countryCode.length < 2) {
  210. if ((filters.seen === false) && (DataManager.wasProfileViewed(results[i].uid) === false)) {
  211. addEntry(results[i])
  212. }
  213. }
  214. }
  215. setTimeout(() => {
  216. scrollBusy = false
  217. $('#list-search').trigger('keydown')
  218. }, 200)
  219. hasMore = results.length >= MAX_PAGE_SIZE
  220. let c = $('table.fflist tbody tr').length
  221. if (filters.seen === false || filters.countryCode.length > 1) {
  222. $('footer h1').html(`Showing ${c} filtered from ${totalCount} of ${maxCount} accounts.`)
  223. } else {
  224. $('footer h1').html(`Showing ${totalCount} of ${maxCount} accounts.`)
  225. }
  226. if (hasMore && ($('table.fflist tbody tr').length < (MAX_PAGE_SIZE * 2))) {
  227. setTimeout(() => {
  228. loadMore()
  229. }, 200)
  230. }
  231. })
  232. }
  233. function addEntry (entry) {
  234. let prettydate = require('pretty-date')
  235. let sex = entry.sex < 0 ? '' : (entry.sex == 0 ? 'is-female' : 'is-male')
  236. let seenRaw = DataManager.wasProfileViewed(entry.uid)
  237. let seenDate = seenRaw !== false ? prettydate.format(seenRaw) : ''
  238. let seen = seenRaw !== false ? 'bright blue' : 'dim'
  239. let bookmarked = DataManager.isBookmarked(entry) ? 'star-full bright yellow' : 'star-empty dim'
  240. $('table.fflist tbody').append(`
  241. <tr id="entry-${entry.uid}" class="entry-${entry.uid} ${sex}">
  242. <td width="64">
  243. <img src="${entry.face}" style="height: 64px; width: 64px;" onError="$(this).hide()" align="bottom" class="avatar">
  244. </td>
  245. <td width="90%">
  246. <div class="seen" title="Last seen ${seenDate}"><i class="icon icon-eye ${seen}"></i></div>
  247. <div class="bookmarked"><i class="icon icon-${bookmarked}"></i></div>
  248. <h1>${entry.nickname}</h1>
  249. <div id="user-${entry.uid}" class="countrylevel" data-seen="Last seen ${seenDate}">
  250. ${entry.countryCode}&nbsp;&nbsp;&nbsp;-&nbsp;&nbsp;&nbsp;<b>Level:</b> ${entry.level}
  251. <div class="cell" style="width: 160px; text-align: right;">
  252. ${seenDate}
  253. </div>
  254. <br>
  255. <div class="cell" style="width: 125px;">
  256. Short ID: <a onClick="copyToClipboard('${entry.short_id}')" title="Click to copy to clipboard.">${entry.short_id}</a>
  257. </div>
  258. <div class="cell" style="width: 160px; text-align: right;">
  259. ID: <a onClick="copyToClipboard('${entry.uid}')" title="Click to copy to clipboard.">${entry.uid}</a>
  260. </div>
  261. </div>
  262. <div id="user-${entry.uid}-buttons" class="buttons">
  263. <a class="button mini view" onClick="showUser('${entry.uid}')">View Account</a>
  264. <a class="button mini fans" onClick="showFollowers('${entry.uid}')"></a>
  265. <a class="button mini following" onClick="showFollowing('${entry.uid}')">0</a>
  266. </div>
  267. </td>
  268. </tr>
  269. `)
  270. LiveMe.getUserInfo(entry.uid).then(user => {
  271. if ((user.count_info.replay_count < 1) && (appSettings.get('general.hide_zeroreplay_followings') === true) && (winType === 1)) {
  272. $('#entry-' + user.user_info.uid).remove()
  273. } else if ((user.count_info.replay_count < 1) && (appSettings.get('general.hide_zeroreplay_fans') === true) && (winType === 0)) {
  274. $('#entry-' + user.user_info.uid).remove()
  275. } else {
  276. $('#entry-' + user.user_info.uid).addClass('entry-' + user.user_info.short_id)
  277. $('#user-' + user.user_info.uid + '-buttons a.view').html(user.count_info.replay_count + ' Replays')
  278. $('#user-' + user.user_info.uid + '-buttons a.fans').html(user.count_info.follower_count + ' Fans')
  279. $('#user-' + user.user_info.uid + '-buttons a.following').html('Following ' + user.count_info.following_count)
  280. }
  281. })
  282. }
  283. function showFollowing (u) { ipcRenderer.send('open-followings-window', { userid: u }) }
  284. function showFollowers (u) { ipcRenderer.send('open-followers-window', { userid: u }) }
  285. function showUser (u) {
  286. $('#entry-' + u).animate({ opacity: 0.3 }, 200); ipcRenderer.send('show-user', { userid: u })
  287. }