<commit_before>var nest = require('depnest')
var {Struct, map, computed, watch} = require('mutant')

exports.needs = nest({
  'profile.obs.recentlyUpdated': 'first',
  'contact.obs.following': 'first',
  'about.obs.name': 'first',
  'about.obs.imageUrl': 'first',
  'intl.sync.startsWith': 'first',
  'keys.sync.id': 'first'
})

exports.gives = nest('profile.async.suggest')

exports.create = function (api) {
  var suggestions = null
  var recentSuggestions = null
  var following = null
  var matches = api.intl.sync.startsWith

  return nest('profile.async.suggest', function () {
    loadSuggestions()
    return function (word, defaultItems) {
      var defaultSuggestions = Array.isArray(defaultItems) && defaultItems.length ? suggestions().filter((item) => {
        return matches(item.title, word) && defaultItems.includes(item.id)
      }) : null

      if (!word) {
        return defaultSuggestions || recentSuggestions()
      } else {
        var result = defaultSuggestions || []

        // prioritize people you follow
        suggestions().forEach((item) => {
          if (following().includes(item.id) && matches(item.title, word) && !result.some(v => v.id === item.id)) {
            result.push(item)
          }
        })

        // next most recently active profiles
        recentSuggestions().forEach((item) => {
          if (matches(item.title, word) && !result.some(v => v.id === item.id)) {
            result.push(item)
          }
        })

        // fallback to everyone
        suggestions().forEach((item) => {
          if (matches(item.title, word) && !result.some(v => v.id === item.id)) {
            result.push(item)
          }
        })
        return result
      }
    }
  })

  function loadSuggestions () {
    if (!suggestions) {
      var id = api.keys.sync.id()
      following = api.contact.obs.following(id)
      var recentlyUpdated = api.profile.obs.recentlyUpdated()
      var contacts = computed([following, recentlyUpdated], function (a, b) {
        var result = Array.from(a)
        b.forEach((item, i) => {
          if (!result.includes(item)) {
            result.push(item)
          }
        })
        return result
      })

      recentSuggestions = map(computed(recentlyUpdated, (items) => Array.from(items).slice(0, 40)), suggestion, {idle: true})
      suggestions = map(contacts, suggestion, {idle: true})
      watch(recentSuggestions)
      watch(suggestions)
    }
  }

  function suggestion (id) {
    var name = api.about.obs.name(id)
    return Struct({
      title: name,
      id,
      subtitle: id.substring(0, 10),
      value: computed([name, id], mention, {idle: true}),
      cls: computed([id, following], followingClass, {idle: true}),
      image: api.about.obs.imageUrl(id),
      showBoth: true
    })
  }
}

function mention (name, id) {
  return `[@${name}](${id})`
}
<commit_msg>for now to improv perf, only suggest people you follow (until new suggest works)<commit_after>var nest = require('depnest')
var {Struct, map, computed, watch, Value} = require('mutant')

exports.needs = nest({
  'profile.obs.recentlyUpdated': 'first',
  'contact.obs.following': 'first',
  'about.obs.name': 'first',
  'about.obs.imageUrl': 'first',
  'intl.sync.startsWith': 'first',
  'keys.sync.id': 'first'
})

exports.gives = nest('profile.async.suggest')

exports.create = function (api) {
  var suggestions = null
  var recentSuggestions = null
  var following = null
  var matches = api.intl.sync.startsWith

  return nest('profile.async.suggest', function () {
    loadSuggestions()
    return function (word, defaultItems) {
      var defaultSuggestions = Array.isArray(defaultItems) && defaultItems.length ? suggestions().filter((item) => {
        return matches(item.title, word) && defaultItems.includes(item.id)
      }) : null

      if (!word) {
        return defaultSuggestions || recentSuggestions()
      } else {
        var result = defaultSuggestions || []

        // prioritize people you follow
        suggestions().forEach((item) => {
          if (following().includes(item.id) && matches(item.title, word) && !result.some(v => v.id === item.id)) {
            result.push(item)
          }
        })

        // next most recently active profiles
        recentSuggestions().forEach((item) => {
          if (matches(item.title, word) && !result.some(v => v.id === item.id)) {
            result.push(item)
          }
        })

        // fallback to everyone
        suggestions().forEach((item) => {
          if (matches(item.title, word) && !result.some(v => v.id === item.id)) {
            result.push(item)
          }
        })
        return result
      }
    }
  })

  function loadSuggestions () {
    if (!suggestions) {
      var id = api.keys.sync.id()
      following = api.contact.obs.following(id)
      // var recentlyUpdated = api.profile.obs.recentlyUpdated()
      // var contacts = computed([following], function (a, b) {
      //   var result = Array.from(a)
      //   b.forEach((item, i) => {
      //     if (!result.includes(item)) {
      //       result.push(item)
      //     }
      //   })
      //   return result
      // })

      recentSuggestions = Value([]) // map(computed(recentlyUpdated, (items) => Array.from(items).slice(0, 40)), suggestion, {idle: true})
      suggestions = map(following, suggestion, {idle: true})
      watch(recentSuggestions)
      watch(suggestions)
    }
  }

  function suggestion (id) {
    var name = api.about.obs.name(id)
    return Struct({
      title: name,
      id,
      subtitle: id.substring(0, 10),
      value: computed([name, id], mention, {idle: true}),
      cls: computed([id, following], followingClass, {idle: true}),
      image: api.about.obs.imageUrl(id),
      showBoth: true
    })
  }
}

function mention (name, id) {
  return `[@${name}](${id})`
}

{'fraction_non_alphanumeric': 0.15714041972359666, 'fraction_numerical': 0.002047432178809077, 'mean_word_length': 2.485136741973841, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4490595', 'n_tokens_mistral': 1818, 'n_tokens_neox': 1761, 'n_words': 386}